@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.
@@ -1,54 +1,54 @@
1
- import path from "node:path";
2
- import fs from "node:fs";
3
- import { DockerfileParser } from "dockerfile-ast";
4
- import glob from "fast-glob";
5
- import ignore from "@balena/dockerignore";
6
- import { tarContentDir } from "../utils.js";
1
+ import path from "node:path"
2
+ import fs from "node:fs"
3
+ import { DockerfileParser } from "dockerfile-ast"
4
+ import glob from "fast-glob"
5
+ import ignore from "@balena/dockerignore"
6
+ import { tarContentDir } from "../utils.js"
7
7
 
8
8
  export async function collectContextFromDockerFile(contextDir, dockerfilePath) {
9
9
  if (!fs.existsSync(dockerfilePath)) {
10
- throw "未发现 Dockerfile";
10
+ throw "未发现 Dockerfile"
11
11
  }
12
12
 
13
- let src = [];
13
+ let src = []
14
14
 
15
15
  // 通过 COPY 和 ADD 获取所有context中的文件
16
- const ast = DockerfileParser.parse(fs.readFileSync(dockerfilePath, "utf8"));
16
+ const ast = DockerfileParser.parse(fs.readFileSync(dockerfilePath, "utf8"))
17
17
  for (let a of ast.getInstructions()) {
18
18
  if (["COPY", "ADD"].includes(a.getInstruction())) {
19
- const from = a.getArguments()[0].getValue().replace(/^\//, "");
20
- const fromFullPath = path.resolve(contextDir, from);
19
+ const from = a.getArguments()[0].getValue().replace(/^\//, "")
20
+ const fromFullPath = path.resolve(contextDir, from)
21
21
 
22
22
  if (fs.existsSync(fromFullPath)) {
23
- const stat = fs.statSync(fromFullPath);
23
+ const stat = fs.statSync(fromFullPath)
24
24
  if (stat.isDirectory()) {
25
25
  let files = await glob(path.join(from, "**"), {
26
- cwd: contextDir,
27
- });
28
- src = src.concat(files);
26
+ cwd: contextDir
27
+ })
28
+ src = src.concat(files)
29
29
  } else if (stat.isFile()) {
30
- src.push(from);
30
+ src.push(from)
31
31
  }
32
32
  } else {
33
33
  // try use glob
34
34
  let files = await glob(from, {
35
- cwd: contextDir,
36
- });
37
- src = src.concat(files);
35
+ cwd: contextDir
36
+ })
37
+ src = src.concat(files)
38
38
  }
39
39
  }
40
40
  }
41
41
  // filter by dockerignore
42
- const dockerIgnoreFile = path.join(contextDir, ".dockerignore");
42
+ const dockerIgnoreFile = path.join(contextDir, ".dockerignore")
43
43
  if (fs.existsSync(dockerIgnoreFile)) {
44
- let ig = ignore();
45
- let data = fs.readFileSync(dockerIgnoreFile, "utf8");
46
- ig.add(data.split("\n"));
47
- src = ig.filter(src);
44
+ let ig = ignore()
45
+ let data = fs.readFileSync(dockerIgnoreFile, "utf8")
46
+ ig.add(data.split("\n"))
47
+ src = ig.filter(src)
48
48
  }
49
49
 
50
- const dockerfile = path.relative(contextDir, dockerfilePath);
51
- src.push(dockerfile); // DON'T IGNORE DOCKERFILE
52
- const output = path.join(contextDir, "lzc-build-image-context.tar");
53
- return await tarContentDir(src, output, contextDir);
50
+ const dockerfile = path.relative(contextDir, dockerfilePath)
51
+ src.push(dockerfile) // DON'T IGNORE DOCKERFILE
52
+ const output = path.join(contextDir, "lzc-build-image-context.tar")
53
+ return await tarContentDir(src, output, contextDir)
54
54
  }
@@ -1,26 +1,27 @@
1
- import logger from "loglevel";
2
- import fs from "node:fs";
3
- import path from "node:path";
4
- import { loadFromYaml, Downloader } from "../utils.js";
5
- import { spawnSync } from "node:child_process";
6
- import { DebugBridge } from "./lpk_debug_bridge.js";
7
- import shellapi from "../shellapi.js";
1
+ import logger from "loglevel"
2
+ import fs from "node:fs"
3
+ import path from "node:path"
4
+ import { loadFromYaml, Downloader } from "../utils.js"
5
+ import { spawnSync } from "node:child_process"
6
+ import { DebugBridge } from "./lpk_debug_bridge.js"
7
+ import shellapi from "../shellapi.js"
8
+ import { triggerApk } from "./apkshell.js"
8
9
 
9
10
  // 从一个目录中找出修改时间最新的包
10
11
  function findOnceLpkByDir(dir = process.cwd()) {
11
12
  const pkg = fs
12
13
  .readdirSync(dir)
13
14
  .map((filename) => {
14
- const stat = fs.statSync(path.resolve(dir, filename));
15
- return { filename, mtime: stat.mtime };
15
+ const stat = fs.statSync(path.resolve(dir, filename))
16
+ return { filename, mtime: stat.mtime }
16
17
  })
17
18
  .sort((a, b) => {
18
- return b.mtime - a.mtime;
19
+ return b.mtime - a.mtime
19
20
  })
20
21
  .find((entry) => {
21
- return entry.filename.endsWith(".lpk");
22
- });
23
- return pkg?.filename ? path.resolve(dir, pkg.filename) : "";
22
+ return entry.filename.endsWith(".lpk")
23
+ })
24
+ return pkg?.filename ? path.resolve(dir, pkg.filename) : ""
24
25
  }
25
26
 
26
27
  export class LpkInstaller {
@@ -31,77 +32,86 @@ export class LpkInstaller {
31
32
  // deploy 构建和安装
32
33
  async deploy(builder) {
33
34
  if (!builder) {
34
- throw "deploy 必须传递一个 builder";
35
+ throw "deploy 必须传递一个 builder"
35
36
  }
36
37
 
37
- let manifest = await builder.getManifest();
38
- let pkgPath = await builder.exec();
39
- logger.info("开始部署应用");
40
- const bridge = new DebugBridge();
41
- await bridge.install(pkgPath, manifest["package"]);
42
- const appUrl = `https://${manifest["application"]["subdomain"]}.${shellapi.boxname}.heiyu.space`;
43
- logger.info(`👉 请在浏览器中访问 ${appUrl}`);
38
+ let pkgPath = await builder.exec()
39
+ logger.info("开始部署应用")
40
+ // FIXME: 这里是前面exec输出的pkgPath还有异步的地方没有await到,临时setTimeout处理一下,后期让@llh看一下
41
+ await new Promise((resolve, reject) => {
42
+ setTimeout(async () => {
43
+ await this.installFromFile(pkgPath)
44
+ .then(() => resolve(true))
45
+ .catch(reject)
46
+ }, 50)
47
+ })
44
48
  }
45
49
 
46
50
  async install(pkgPath) {
47
51
  if (pkgPath.startsWith("http")) {
48
- return this.installFromUrl(pkgPath);
52
+ return this.installFromUrl(pkgPath)
49
53
  } else if (fs.statSync(pkgPath).isDirectory()) {
50
- return this.installFromDirectory(pkgPath);
54
+ return this.installFromDirectory(pkgPath)
51
55
  } else {
52
- return this.installFromFile(pkgPath);
56
+ return this.installFromFile(pkgPath)
53
57
  }
54
58
  }
55
59
 
56
60
  async installFromDirectory(dir) {
57
- const lpk = findOnceLpkByDir(dir);
61
+ const lpk = findOnceLpkByDir(dir)
58
62
  if (lpk) {
59
- logger.info(`正在安装自动扫描出来的lpk包(${lpk})`);
63
+ logger.info(`正在安装自动扫描出来的lpk包(${lpk})`)
60
64
  }
61
- return this.installFromFile(lpk);
65
+ return this.installFromFile(lpk)
62
66
  }
63
67
 
64
68
  async installFromUrl(url) {
65
- let downloader = new Downloader();
66
- const tempDir = fs.mkdtempSync(".lzc-cli-install");
69
+ let downloader = new Downloader()
70
+ const tempDir = fs.mkdtempSync(".lzc-cli-install")
67
71
  try {
68
- let pkgPath = path.join(tempDir, "a.lpk");
69
- logger.debug("开始下载lpk");
70
- await downloader.download(url, pkgPath);
71
- logger.debug("下载完成", pkgPath);
72
- await this.installFromFile(pkgPath);
72
+ let pkgPath = path.join(tempDir, "a.lpk")
73
+ logger.debug("开始下载lpk")
74
+ await downloader.download(url, pkgPath)
75
+ logger.debug("下载完成", pkgPath)
76
+ await this.installFromFile(pkgPath)
73
77
  } catch (e) {
74
- throw e;
78
+ throw e
75
79
  } finally {
76
- fs.rmSync(tempDir, { recursive: true });
80
+ fs.rmSync(tempDir, { recursive: true })
77
81
  }
78
82
  }
79
83
 
80
84
  async installFromFile(pkgPath) {
81
85
  if (!pkgPath) {
82
- throw "install 必须指定一个 pkg 路径";
86
+ throw "install 必须指定一个 pkg 路径"
83
87
  }
84
88
 
85
89
  if (!fs.existsSync(pkgPath)) {
86
- throw `${pkgPath} 不存在`;
90
+ throw `${pkgPath} 不存在`
87
91
  }
88
92
 
89
- const tempDir = fs.mkdtempSync(".lzc-cli-install");
90
- let manifest;
93
+ const tempDir = fs.mkdtempSync(".lzc-cli-install")
94
+ let manifest
91
95
  try {
92
- spawnSync("unzip", ["-d", tempDir, pkgPath]);
93
- manifest = loadFromYaml(path.join(tempDir, "manifest.yml"));
94
- logger.debug("lpk manifest", manifest);
96
+ spawnSync("unzip", ["-d", tempDir, pkgPath])
97
+ manifest = loadFromYaml(path.join(tempDir, "manifest.yml"))
98
+ await triggerApk(
99
+ manifest["package"],
100
+ manifest["name"],
101
+ path.resolve(path.join(tempDir, "icon.png"))
102
+ )
103
+ logger.debug("lpk manifest", manifest)
95
104
  } finally {
96
- fs.rmSync(tempDir, { recursive: true });
105
+ fs.rmSync(tempDir, { recursive: true })
97
106
  }
98
107
 
99
- const bridge = new DebugBridge();
100
- logger.info("开始安装应用");
101
- await bridge.install(pkgPath, manifest["package"]);
102
- logger.info(`安装成功!`);
108
+ const bridge = new DebugBridge()
109
+ logger.info("开始安装应用")
110
+ await bridge.install(pkgPath, manifest["package"])
111
+ logger.info("\n")
112
+ logger.info(`安装成功!`)
103
113
  logger.info(
104
114
  `👉 请在浏览器中访问 https://${manifest["application"]["subdomain"]}.${shellapi.boxname}.heiyu.space`
105
- );
115
+ )
106
116
  }
107
117
  }
@@ -1,7 +1,7 @@
1
- import { Publish } from "./publish.js";
2
- import { PrePublish } from "./prePublish.js";
3
- import { reLogin } from "./login.js";
4
- import fs from "node:fs";
1
+ import { Publish } from "./publish.js"
2
+ import { PrePublish } from "./prePublish.js"
3
+ import { reLogin } from "./login.js"
4
+ import fs from "node:fs"
5
5
 
6
6
  export function appstoreCommand(program) {
7
7
  let subCommands = [
@@ -9,8 +9,8 @@ export function appstoreCommand(program) {
9
9
  command: "login",
10
10
  desc: "登录",
11
11
  handler: async () => {
12
- await reLogin();
13
- },
12
+ await reLogin()
13
+ }
14
14
  },
15
15
  {
16
16
  command: "pre-publish <pkgPath>",
@@ -19,26 +19,26 @@ export function appstoreCommand(program) {
19
19
  args.option("c", {
20
20
  alias: "changelog",
21
21
  describe: "更改日志",
22
- type: "string",
23
- });
22
+ type: "string"
23
+ })
24
24
  args.option("F", {
25
25
  alias: "file",
26
26
  describe: "更改日志文件",
27
- type: "string",
28
- });
27
+ type: "string"
28
+ })
29
29
  args.option("G", {
30
30
  alias: "gid",
31
31
  describe: "内测组ID",
32
- type: "string",
33
- });
32
+ type: "string"
33
+ })
34
34
  },
35
35
  handler: async ({ pkgPath, changelog, file, gid }) => {
36
- const p = new PrePublish();
36
+ const p = new PrePublish()
37
37
  if (!changelog && file) {
38
- changelog = fs.readFileSync(file, "utf8");
38
+ changelog = fs.readFileSync(file, "utf8")
39
39
  }
40
- await p.publish(pkgPath, changelog, gid);
41
- },
40
+ await p.publish(pkgPath, changelog, gid)
41
+ }
42
42
  },
43
43
  {
44
44
  command: "publish <pkgPath>",
@@ -47,29 +47,29 @@ export function appstoreCommand(program) {
47
47
  args.option("c", {
48
48
  alias: "changelog",
49
49
  describe: "更改日志",
50
- type: "string",
51
- });
50
+ type: "string"
51
+ })
52
52
  args.option("F", {
53
53
  alias: "file",
54
54
  describe: "更改日志文件",
55
- type: "string",
56
- });
55
+ type: "string"
56
+ })
57
57
  },
58
58
  handler: async ({ pkgPath, changelog, file }) => {
59
- const p = new Publish();
59
+ const p = new Publish()
60
60
  if (!changelog && file) {
61
- changelog = fs.readFileSync(file, "utf8");
61
+ changelog = fs.readFileSync(file, "utf8")
62
62
  }
63
- await p.publish(pkgPath, changelog);
64
- },
65
- },
66
- ];
63
+ await p.publish(pkgPath, changelog)
64
+ }
65
+ }
66
+ ]
67
67
 
68
68
  program.command({
69
69
  command: "appstore",
70
70
  desc: "应用商店",
71
71
  builder: (args) => {
72
- args.command(subCommands);
73
- },
74
- });
72
+ args.command(subCommands)
73
+ }
74
+ })
75
75
  }
@@ -1,145 +1,145 @@
1
- import fetch from "node-fetch";
2
- import path from "path";
3
- import logger from "loglevel";
4
- import env from "../env.js";
5
- import inquirer from "inquirer";
6
- import FormData from "form-data";
1
+ import fetch from "node-fetch"
2
+ import path from "path"
3
+ import logger from "loglevel"
4
+ import env from "../env.js"
5
+ import inquirer from "inquirer"
6
+ import FormData from "form-data"
7
7
 
8
- const accountServerUrl = "https://account.lazycat.cloud";
8
+ const accountServerUrl = "https://account.lazycat.cloud"
9
9
 
10
10
  function join(...params) {
11
- var x = path.join(...params);
12
- return x;
11
+ var x = path.join(...params)
12
+ return x
13
13
  }
14
14
 
15
15
  function login(username, password) {
16
- const form = new FormData();
17
- form.append("username", username);
18
- form.append("password", password);
16
+ const form = new FormData()
17
+ form.append("username", username)
18
+ form.append("password", password)
19
19
 
20
20
  return fetch(join(accountServerUrl, "/api/login/signin"), {
21
21
  method: "POST",
22
22
  headers: {
23
- "content-type": `multipart/form-data; boundary=${form.getBoundary()}`,
23
+ "content-type": `multipart/form-data; boundary=${form.getBoundary()}`
24
24
  },
25
- body: form,
25
+ body: form
26
26
  })
27
27
  .then(async (res) => {
28
- let bodyText = await res.text();
29
- let body = JSON.parse(bodyText);
28
+ let bodyText = await res.text()
29
+ let body = JSON.parse(bodyText)
30
30
  if (body.success) {
31
- return Promise.resolve(body.data);
31
+ return Promise.resolve(body.data)
32
32
  }
33
- return Promise.reject(body.message);
33
+ return Promise.reject(body.message)
34
34
  })
35
35
  .then((data) => {
36
- env.set({ token: data.token }, true);
37
- logger.info("登录成功!");
38
- });
36
+ env.set({ token: data.token }, true)
37
+ logger.info("登录成功!")
38
+ })
39
39
  }
40
40
 
41
41
  async function isLogin() {
42
42
  try {
43
- let token = env.get("token");
43
+ let token = env.get("token")
44
44
  if (!token) {
45
- return false;
45
+ return false
46
46
  }
47
47
  return fetch(join(accountServerUrl, "/api/user/current"), {
48
48
  method: "GET",
49
49
  headers: {
50
- "X-User-Token": token,
51
- },
50
+ "X-User-Token": token
51
+ }
52
52
  }).then(async (res) => {
53
- let bodyText = await res.text();
54
- let body = JSON.parse(bodyText);
53
+ let bodyText = await res.text()
54
+ let body = JSON.parse(bodyText)
55
55
  if (body.success) {
56
- return token;
56
+ return token
57
57
  }
58
- logger.debug(body.message);
59
- return false;
60
- });
58
+ logger.debug(body.message)
59
+ return false
60
+ })
61
61
  } catch (e) {
62
- logger.trace(e);
63
- return false;
62
+ logger.trace(e)
63
+ return false
64
64
  }
65
65
  }
66
66
 
67
67
  async function askUserInfo() {
68
- const noEmpty = (value) => value != "";
68
+ const noEmpty = (value) => value != ""
69
69
  return await inquirer.prompt([
70
70
  {
71
71
  type: "input",
72
72
  name: "username",
73
73
  message: "请输入登录用户名",
74
- validate: noEmpty,
74
+ validate: noEmpty
75
75
  },
76
76
  {
77
77
  type: "password",
78
78
  mask: "*",
79
79
  name: "password",
80
80
  message: "请输入登录密码",
81
- validate: noEmpty,
82
- },
83
- ]);
81
+ validate: noEmpty
82
+ }
83
+ ])
84
84
  }
85
85
 
86
86
  async function interactiveLogin() {
87
87
  try {
88
- let info = await askUserInfo();
89
- await login(info.username, info.password);
88
+ let info = await askUserInfo()
89
+ await login(info.username, info.password)
90
90
  } catch (e) {
91
- logger.debug("login error: ", e);
92
- logger.info("帐号或者密码错误,请重新输入!");
93
- return interactiveLogin();
91
+ logger.debug("login error: ", e)
92
+ logger.info("帐号或者密码错误,请重新输入!")
93
+ return interactiveLogin()
94
94
  }
95
95
  }
96
96
 
97
97
  export async function reLogin() {
98
- let token = await isLogin();
98
+ let token = await isLogin()
99
99
  if (token) {
100
100
  const questions = [
101
101
  {
102
102
  name: "relogin",
103
103
  type: "input",
104
104
  default: "n",
105
- message: "检测到已经登录,是否重新登录(y/n):",
106
- },
107
- ];
108
- const answers = await inquirer.prompt(questions);
105
+ message: "检测到已经登录,是否重新登录(y/n):"
106
+ }
107
+ ]
108
+ const answers = await inquirer.prompt(questions)
109
109
  if (answers.relogin.toLowerCase() === "n") {
110
- logger.info(`token: ${token}`);
111
- return;
110
+ logger.info(`token: ${token}`)
111
+ return
112
112
  }
113
113
  }
114
- await interactiveLogin();
114
+ await interactiveLogin()
115
115
  }
116
116
 
117
117
  export async function autoLogin() {
118
- let token = await isLogin();
118
+ let token = await isLogin()
119
119
  if (token) {
120
- logger.debug("appstore 已经登录");
121
- return;
120
+ logger.debug("appstore 已经登录")
121
+ return
122
122
  }
123
123
 
124
- logger.debug("token错误,尝试自动登录");
125
- await interactiveLogin();
124
+ logger.debug("token错误,尝试自动登录")
125
+ await interactiveLogin()
126
126
  }
127
127
 
128
128
  export async function request(url, options = {}) {
129
- await autoLogin();
129
+ await autoLogin()
130
130
 
131
- const token = env.get("token");
131
+ const token = env.get("token")
132
132
 
133
133
  let headers = {
134
134
  "X-User-Token": token,
135
- cookie: `userToken=${token}`,
136
- };
135
+ cookie: `userToken=${token}`
136
+ }
137
137
  if (options.headers) {
138
- headers = Object.assign({}, options.headers, headers);
138
+ headers = Object.assign({}, options.headers, headers)
139
139
  }
140
140
 
141
- options = Object.assign({}, options, { headers });
142
- logger.trace(`fetch ${url}`, options);
141
+ options = Object.assign({}, options, { headers })
142
+ logger.trace(`fetch ${url}`, options)
143
143
 
144
- return fetch(url, options);
144
+ return fetch(url, options)
145
145
  }