@lazycatcloud/lzc-cli 1.1.7 → 1.1.9

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.
Files changed (105) hide show
  1. package/README.md +69 -11
  2. package/lib/api.js +71 -36
  3. package/lib/app/index.js +79 -23
  4. package/lib/app/lpk_build.js +96 -52
  5. package/lib/app/lpk_create.js +63 -41
  6. package/lib/app/lpk_create_generator.js +202 -0
  7. package/lib/app/lpk_devshell.js +393 -328
  8. package/lib/app/lpk_devshell_docker.js +211 -0
  9. package/lib/app/lpk_installer.js +63 -26
  10. package/lib/app/lpk_log.js +68 -0
  11. package/lib/app/lpk_status.js +18 -0
  12. package/lib/app/lpk_uninstall.js +19 -0
  13. package/lib/appstore/index.js +37 -0
  14. package/lib/appstore/login.js +137 -0
  15. package/lib/appstore/publish.js +62 -0
  16. package/lib/autologin.js +0 -80
  17. package/lib/box/api/clientapi.js +1322 -0
  18. package/lib/box/api/empty.js +35 -0
  19. package/lib/box/check_qemu.js +1 -0
  20. package/lib/box/index.js +41 -94
  21. package/lib/box/qemu_vm_mgr.js +208 -239
  22. package/lib/box/schemes/vm_box_system_debian.json +1 -1
  23. package/lib/docker-compose.js +1 -2
  24. package/lib/env.js +23 -142
  25. package/lib/key.js +1 -0
  26. package/lib/sdk.js +10 -25
  27. package/lib/utils.js +156 -233
  28. package/package.json +19 -11
  29. package/scripts/cli.js +14 -135
  30. package/template/_lpk/README.md +31 -0
  31. package/template/_lpk/exec.sh +19 -0
  32. package/template/_lpk/golang.manifest.yml.in +16 -0
  33. package/template/_lpk/lazycat.png +0 -0
  34. package/template/_lpk/lite.manifest.yml.in +19 -0
  35. package/template/_lpk/local_devshell/Dockerfile +16 -0
  36. package/template/_lpk/local_devshell/build.sh +5 -0
  37. package/template/_lpk/local_devshell/entrypoint.sh +87 -0
  38. package/template/{_lazycat/debug/shell → _lpk/local_devshell}/sshd_config +8 -8
  39. package/template/_lpk/manifest.yml.in +0 -1
  40. package/template/{vue/lzc-build.yml → _lpk/vue.lzc-build.yml.in} +9 -1
  41. package/template/golang/README.md +0 -2
  42. package/template/golang/_gitignore +2 -0
  43. package/template/golang/build.sh +6 -0
  44. package/template/golang/lazycat.png +0 -0
  45. package/template/golang/lzc-build.yml +9 -1
  46. package/template/golang/rego.go +15 -16
  47. package/template/golang/rego_test.go +13 -0
  48. package/template/ionic_vue3/lazycat.png +0 -0
  49. package/template/ionic_vue3/lzc-build.yml +9 -1
  50. package/template/lite/error_pages/502.html.tpl +13 -0
  51. package/template/lite/lazycat.png +0 -0
  52. package/template/lite/lzc-build.yml +60 -0
  53. package/cmds/app.js +0 -133
  54. package/cmds/config.js +0 -55
  55. package/cmds/create.js +0 -55
  56. package/cmds/dev.js +0 -130
  57. package/cmds/init.js +0 -125
  58. package/cmds/log.js +0 -103
  59. package/cmds/publish.js +0 -116
  60. package/lib/archiver.js +0 -105
  61. package/lib/box/hportal.js +0 -120
  62. package/lib/builder.js +0 -313
  63. package/lib/dev.js +0 -314
  64. package/lib/generator.js +0 -146
  65. package/template/_lazycat/_gitignore +0 -1
  66. package/template/_lazycat/app-config +0 -1
  67. package/template/_lazycat/debug/devforward/50x.html +0 -30
  68. package/template/_lazycat/debug/devforward/Dockerfile +0 -16
  69. package/template/_lazycat/debug/devforward/docker-compose.override.yml.in +0 -11
  70. package/template/_lazycat/debug/devforward/entrypoint.sh +0 -10
  71. package/template/_lazycat/debug/devforward/nginx.conf.template +0 -56
  72. package/template/_lazycat/debug/devforward/sshd_config +0 -116
  73. package/template/_lazycat/debug/shell/50x.html +0 -32
  74. package/template/_lazycat/debug/shell/Dockerfile +0 -18
  75. package/template/_lazycat/debug/shell/build.sh +0 -15
  76. package/template/_lazycat/debug/shell/docker-compose.override.yml.in +0 -13
  77. package/template/_lazycat/debug/shell/entrypoint.sh +0 -12
  78. package/template/_lazycat/docker-compose.yml.in +0 -15
  79. package/template/_lazycat/icon.svg +0 -1
  80. package/template/_lazycat/screenshot.png +0 -0
  81. package/template/_lpk/sync/Dockerfile +0 -16
  82. package/template/_lpk/sync/build.sh +0 -5
  83. package/template/_lpk/sync/entrypoint.sh +0 -8
  84. package/template/_lpk/sync/sshd_config +0 -117
  85. package/template/_lpk/sync.manifest.yml.in +0 -3
  86. package/template/release/golang/Dockerfile +0 -18
  87. package/template/release/golang/build.sh +0 -13
  88. package/template/release/ionic_vue3/Dockerfile +0 -10
  89. package/template/release/ionic_vue3/build.sh +0 -7
  90. package/template/release/ionic_vue3/docker-compose.yml.in +0 -3
  91. package/template/release/vue/Dockerfile +0 -10
  92. package/template/release/vue/build.sh +0 -10
  93. package/template/release/vue/docker-compose.yml.in +0 -3
  94. package/template/vue/README.md +0 -29
  95. package/template/vue/_dockerignore +0 -1
  96. package/template/vue/babel.config.js +0 -3
  97. package/template/vue/package.json +0 -43
  98. package/template/vue/public/favicon.ico +0 -0
  99. package/template/vue/public/index.html +0 -33
  100. package/template/vue/src/App.vue +0 -39
  101. package/template/vue/src/main.js +0 -8
  102. package/template/vue/src/todo.vue +0 -640
  103. package/template/vue/src/top-bar.vue +0 -100
  104. package/template/vue/src/webdav.vue +0 -183
  105. package/template/vue/vue.config.js +0 -21
package/README.md CHANGED
@@ -1,21 +1,79 @@
1
- ## 开始使用
1
+ # 懒猫云应用命令行工具
2
+ ```
3
+ <command> [options]
4
+
5
+ Commands:
6
+ lzc-cli box 盒子管理 lzc-cli app 应用管理 lzc-cli project 项目管理 lzc-cli appstore 应用商店
7
+ Options:
8
+ -h, --help [boolean] [default: false]
9
+ --version Show version number [boolean]
10
+ --log log level 'trace', 'debug', 'info', 'warn', 'error'
11
+ [string] [default: "info"]
12
+ ```
13
+
14
+ ## 安装
15
+ ```
16
+ npm install -g @lazycatcloud/lzc-cli
17
+ ```
18
+
19
+ ## 虚拟盒子
20
+
21
+ ### 创建虚拟盒子
22
+ ```
23
+ lzc-cli box create
24
+ ```
25
+ 将从 https://dl.lazycat.cloud 中下载最新的盒子系统数据,跟创建对应的 qemu 虚拟盒子。
26
+
27
+ ### 启动盒子
28
+ ```
29
+ lzc-cli box start <boxname>
30
+ # lzc-cli box start mydemobox
31
+ ```
32
+ 启动盒子成功后,就可以在 https://<mydemobox>.heiyu.space 中看到盒子的主页了。
33
+
34
+ ### 切换默认的盒子
35
+ ```
36
+ lzc-cli box switch <otherBoxName>
37
+ ```
38
+
39
+ ### 查看本地的虚拟盒子信息
40
+ ```
41
+ lzc-cli box info
42
+ ```
2
43
 
3
- ### 命令行工具使用方法
44
+ ## 应用管理
4
45
 
5
- #### 创建项目
46
+ ### 安装应用到盒子中去
6
47
 
7
- ```bash
8
- lzc-cli create a_project
48
+ - 从 https://repo.lazycat.cloud 中安装
49
+ ```
50
+ lzc-cli app install https://repo.lazycat.cloud/pkgs/cloud.lazycat.app.kityminder/cloud.lazycat.app.kityminder-v1.0.3.lpk
9
51
  ```
10
52
 
11
- #### 在本地打包镜像, 如果本地没有发布应用相关文件,会先执行 `init` 命令
53
+ - 从本地安装
54
+ ```
55
+ lzc-cli app install ./kityminder.lpk
56
+ ```
12
57
 
13
- ```bash
14
- lzc-cli build
58
+ ### 卸载应用
59
+ ```
60
+ lzc-cli app uninstall cloud.lazycat.app.kityminder
15
61
  ```
16
62
 
17
- #### 发布 app 至 app p 至 appdb
63
+ ## 项目管理
18
64
 
19
- ```bash
20
- lzc-cli publish
65
+ ### 初始化懒猫云应用
66
+ ```
67
+ lzc-cli project create yourappname
68
+ ```
69
+
70
+ ### 构建 lpk 包
71
+ ```
72
+ lzc-cli project build -o yourappname.lpk
73
+ ```
74
+
75
+ ### 盒子内开发
76
+ ```
77
+ lzc-cli project devshell -b
21
78
  ```
79
+ `-b` 表示是否重新构建盒子中项目环境。
package/lib/api.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import ora from "ora";
2
2
  import chalk from "chalk";
3
3
  import fs from "fs";
4
- import { request } from "./autologin.js";
4
+ import logger from "loglevel";
5
+ import fetch from "node-fetch";
5
6
 
6
7
  //
7
8
  // sdk 提供的API
@@ -10,10 +11,12 @@ export default class API {
10
11
  this.appId = appId;
11
12
  this.host = host;
12
13
  }
13
- async applyZip(zipPath, params) {
14
- let searchParams = new URLSearchParams(params);
15
- const resp = await request(
16
- `${this.host}/api/v1/app/applyZip?${searchParams.toString()}`,
14
+ async install(zipPath) {
15
+ if (!fs.existsSync(zipPath)) {
16
+ throw `${zipPath} 不存在`;
17
+ }
18
+ const resp = await fetch(
19
+ `${this.host}/api/v1/app/install?id=${this.appId}`,
17
20
  {
18
21
  method: "POST",
19
22
  body: fs.createReadStream(zipPath),
@@ -22,33 +25,65 @@ export default class API {
22
25
  if (resp.status != 200) {
23
26
  throw chalk.red(await resp.text());
24
27
  }
25
- // update
26
28
  }
27
- // applyZip api 支持以下query
28
- // build boolean 是否构建app容器
29
- // pull boolean 是否从docker.io拉取image
30
- async install(zipPath, params) {
31
- const resp = await request(
32
- `${this.host}/api/v1/app/install`,
29
+
30
+ async uninstall() {
31
+ return await fetch(`${this.host}/api/v1/app/uninstall?id=${this.appId}`, {
32
+ method: "DELETE",
33
+ });
34
+ }
35
+
36
+ async resume() {
37
+ const resp = await fetch(
38
+ `${this.host}/api/v1/app/resume?id=${this.appId}`,
33
39
  {
34
40
  method: "POST",
35
- body: fs.createReadStream(zipPath),
36
41
  }
37
42
  );
38
43
  if (resp.status != 200) {
39
- throw chalk.red(await resp.text());
44
+ const text = await resp.text();
45
+ throw text;
40
46
  }
41
- // update
42
47
  }
43
48
 
44
- async uninstall() {
45
- return await request(`${this.host}/api/v1/app/uninstall?id=${this.appId}`, {
46
- method: "DELETE",
47
- });
49
+ async hasMount() {
50
+ const resp = await fetch(
51
+ `${this.host}/api/v1/app/hasMount?id=${this.appId}`,
52
+ {
53
+ method: "GET",
54
+ }
55
+ );
56
+ if (resp.status == 200) {
57
+ return true;
58
+ } else {
59
+ const text = await resp.text();
60
+ if (text) {
61
+ logger.debug("hasMount request failed", text);
62
+ }
63
+ return false;
64
+ }
65
+ }
66
+
67
+ async isDevshell() {
68
+ const resp = await fetch(
69
+ `${this.host}/api/v1/app/isDevshell?id=${this.appId}`,
70
+ {
71
+ method: "GET",
72
+ }
73
+ );
74
+ if (resp.status == 200) {
75
+ return true;
76
+ } else {
77
+ const text = await resp.text();
78
+ if (text) {
79
+ logger.debug("isDevshell request failed", text);
80
+ }
81
+ return false;
82
+ }
48
83
  }
49
84
 
50
85
  async status() {
51
- const resp = await request(`${this.host}/api/v1/app/status?id=${this.appId}`);
86
+ const resp = await fetch(`${this.host}/api/v1/app/status?id=${this.appId}`);
52
87
  if (resp.status == 200) {
53
88
  const status = await resp.json();
54
89
  return status;
@@ -60,7 +95,7 @@ export default class API {
60
95
  }
61
96
 
62
97
  async postPublicKey(key) {
63
- const resp = await request(`${this.host}/api/v1/register`, {
98
+ const resp = await fetch(`${this.host}/api/v1/register`, {
64
99
  method: "POST",
65
100
  body: key,
66
101
  });
@@ -69,7 +104,7 @@ export default class API {
69
104
  }
70
105
  }
71
106
 
72
- async checkStatus() {
107
+ async checkStatus(resume = false) {
73
108
  const spinner = ora().start();
74
109
  let { status, info } = await this.status();
75
110
  spinner.text = "部署进度 " + status;
@@ -80,12 +115,17 @@ export default class API {
80
115
  break;
81
116
  case "error":
82
117
  spinner.stop();
83
- console.log(status, info);
118
+ logger.error("应用状态错误,请在盒子中查看对应的错误信息");
84
119
  throw info?.msg;
85
120
  default:
86
121
  try {
87
- await desireStatusTimer((result) => {
122
+ await desireStatusTimer(async (result) => {
88
123
  spinner.text = "部署进度 " + result.status;
124
+
125
+ if (result.status == "paused" && resume) {
126
+ await this.resume();
127
+ }
128
+
89
129
  return result.status === "running";
90
130
  }, this.status.bind(this));
91
131
  } catch (error) {
@@ -100,33 +140,28 @@ export default class API {
100
140
  }
101
141
 
102
142
  export function desireStatusTimer(desireCheckFn, getStatusFn) {
103
- const step = 2000;
143
+ let errorCount = 0;
104
144
  return new Promise((resolve, reject) => {
105
145
  function schedule(timeout) {
106
146
  setTimeout(async () => {
147
+ const answer = await getStatusFn();
107
148
  try {
108
- const answer = await getStatusFn();
109
149
  if (answer) {
110
150
  if (answer.status == "error") {
111
- timeout += step;
112
- if (timeout > 1000 * 10) {
113
- reject(new Error(answer.error));
114
- return;
115
- }
116
- schedule(timeout);
117
- } else if (desireCheckFn(answer)) {
151
+ throw new Error(answer.error);
152
+ } else if (await desireCheckFn(answer)) {
118
153
  resolve(answer);
119
154
  } else {
120
155
  schedule(1000);
121
156
  }
122
157
  }
123
158
  } catch (e) {
124
- timeout += step;
125
- if (timeout > 1000 * 10) {
159
+ errorCount += 1;
160
+ if (errorCount >= 3) {
126
161
  reject(e);
127
162
  return;
128
163
  }
129
- schedule(timeout);
164
+ schedule(1000);
130
165
  }
131
166
  }, timeout);
132
167
  }
package/lib/app/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import path from "node:path";
2
- import lpkCreate, { LpkManifest } from "./lpk_create.js";
2
+ import lpkCreate from "./lpk_create.js";
3
3
  import { LpkBuild } from "./lpk_build.js";
4
- import { AppDevShell } from "./lpk_devshell.js";
4
+ import { AppDevShell, fallbackToRsync } from "./lpk_devshell.js";
5
5
  import { LpkInstaller } from "./lpk_installer.js";
6
- import fs from "node:fs";
7
- import { APP_FOLDER } from "../utils.js";
6
+ import { LpkUninstaller } from "./lpk_uninstall.js";
7
+ import { LpkStatuser } from "./lpk_status.js";
8
+ import { LpkLogger } from "./lpk_log.js";
8
9
 
9
10
  export function lpkProjectCommand(program) {
10
11
  let subCommands = [
@@ -12,7 +13,7 @@ export function lpkProjectCommand(program) {
12
13
  command: "create <name>",
13
14
  desc: "创建懒猫云应用",
14
15
  handler: async ({ name }) => {
15
- await lpkCreate({ name });
16
+ await lpkCreate(name);
16
17
  },
17
18
  },
18
19
  {
@@ -21,18 +22,23 @@ export function lpkProjectCommand(program) {
21
22
  builder: (args) => {
22
23
  args.option("o", {
23
24
  alias: "output",
24
- describe: "输出文件夹",
25
+ describe: "输出文件",
26
+ type: "string",
27
+ });
28
+ args.option("f", {
29
+ alias: "file",
30
+ describe: "指定构建的lzc-build.yml文件",
25
31
  type: "string",
26
32
  });
27
33
  },
28
- handler: async ({ context, output }) => {
29
- const lpk = new LpkBuild();
30
- await lpk.init();
34
+ handler: async ({ context, output, file }) => {
35
+ const lpk = await new LpkBuild(context, file).init();
31
36
  // 正常的打包逻辑不需要 devshell
32
37
  lpk.onBeforeBuildPackage(async (options) => {
33
38
  delete options["devshell"];
39
+
34
40
  if (output) {
35
- options["pkgout"] = output;
41
+ options["lpkPath"] = output;
36
42
  }
37
43
  return options;
38
44
  });
@@ -43,20 +49,35 @@ export function lpkProjectCommand(program) {
43
49
  command: "devshell [context]",
44
50
  desc: "进入盒子的开发环境",
45
51
  builder: (args) => {
46
- args.option("b", {
47
- alias: "build",
48
- describe: "重新构建环境",
52
+ args.option("r", {
53
+ alias: "rsync",
54
+ deprecate: true,
55
+ type: "boolean",
56
+ default: fallbackToRsync(),
57
+ });
58
+ const shell = process.env.SHELL
59
+ ? path.basename(process.env.SHELL)
60
+ : "sh";
61
+ args.option("s", {
62
+ alias: "shell",
63
+ describe: "指定你最喜欢的shell",
64
+ type: "string",
65
+ default: shell,
66
+ });
67
+ args.option("f", {
68
+ alias: "force",
69
+ describe: "强制重新构建",
49
70
  type: "boolean",
50
- default: false,
51
71
  });
52
72
  },
53
- handler: async ({ context, build }) => {
54
- const app = new AppDevShell(context);
73
+ handler: async ({ context, shell, rsync, force }) => {
74
+ const app = new AppDevShell(context, undefined, rsync, force);
55
75
  await app.init();
56
- if (build) {
57
- await app.shellWithBuild();
76
+ await app.build();
77
+ if (rsync) {
78
+ await app.rsyncShell(shell);
58
79
  } else {
59
- await app.shell();
80
+ await app.sshfsShell(shell);
60
81
  }
61
82
  },
62
83
  },
@@ -73,12 +94,47 @@ export function lpkProjectCommand(program) {
73
94
  export function lpkAppCommand(program) {
74
95
  let subCommands = [
75
96
  {
76
- command: "install <pkgPath>",
77
- desc: "部署应用至设备",
78
- handler: async ({ pkgPath }) => {
97
+ command: "install <pkgUrl>",
98
+ desc: "部署应用至设备, pkgUrl 可以为路径,或者https://,http://请求地址",
99
+ handler: async ({ pkgUrl }) => {
79
100
  const installer = new LpkInstaller();
80
101
  await installer.init();
81
- await installer.install(pkgPath);
102
+ await installer.install(pkgUrl);
103
+ },
104
+ },
105
+ {
106
+ command: "uninstall <pkgId>",
107
+ desc: "从设备中卸载某一个应用",
108
+ handler: async ({ pkgId }) => {
109
+ const uninstaller = new LpkUninstaller();
110
+ await uninstaller.init();
111
+ await uninstaller.uninstall(pkgId);
112
+ },
113
+ },
114
+ {
115
+ command: "status <pkgId>",
116
+ desc: "获取某一个应用的状态",
117
+ handler: async ({ pkgId }) => {
118
+ const statuser = new LpkStatuser();
119
+ await statuser.init();
120
+ await statuser.status(pkgId);
121
+ },
122
+ },
123
+ {
124
+ command: "log <pkgId>",
125
+ desc: "查看某一个app的日志",
126
+ builder: (args) => {
127
+ args.option("f", {
128
+ alias: "follow",
129
+ describe: "持续输出",
130
+ type: "boolean",
131
+ default: false,
132
+ });
133
+ },
134
+ handler: async ({ pkgId, follow }) => {
135
+ const log = new LpkLogger();
136
+ await log.init();
137
+ await log.start(pkgId, follow);
82
138
  },
83
139
  },
84
140
  ];
@@ -87,11 +87,35 @@ async function fetchIconTo(options, cwd, destDir) {
87
87
  return;
88
88
  }
89
89
 
90
+ // 提供一些方便的环境变量,可以在 lzc-build.yml 中直接使用
91
+ // - LocalIP 本地局域网ip
92
+ function localIp() {
93
+ const output = spawnSync("ip", ["route", "get", "1.1.1.1"], {
94
+ encoding: "utf-8",
95
+ });
96
+ const match = output.stdout.match(/src\ (.+)\ uid/i);
97
+ if (match) {
98
+ return match[1];
99
+ } else {
100
+ logger.debug("get LocalIP environment error", output.stderr);
101
+ return "";
102
+ }
103
+ }
104
+ function convenientEnv() {
105
+ return Object.assign(
106
+ {},
107
+ {
108
+ LocalIP: localIp(),
109
+ },
110
+ process.env
111
+ );
112
+ }
113
+
90
114
  export class LpkBuild {
91
- constructor(cwd) {
115
+ constructor(cwd, lzcBuild = "lzc-build.yml") {
92
116
  this.pwd = cwd ?? process.cwd();
93
117
 
94
- this.optionsFilePath = path.join(this.pwd, "lzc-build.yml");
118
+ this.optionsFilePath = path.join(this.pwd, lzcBuild);
95
119
  this.options = loadFromYaml(this.optionsFilePath);
96
120
 
97
121
  this.manifestFilePath = this.options["manifest"]
@@ -108,9 +132,14 @@ export class LpkBuild {
108
132
  // init 时替换 lzc-build.yml 中的模板字段
109
133
  async init() {
110
134
  const manifest = await this.getManifest();
135
+ const primitive = convenientEnv();
111
136
  this.options = yaml.load(
112
- await envTemplateFile(this.optionsFilePath, manifest)
137
+ await envTemplateFile(
138
+ this.optionsFilePath,
139
+ Object.assign({}, primitive, manifest)
140
+ )
113
141
  );
142
+ return this;
114
143
  }
115
144
 
116
145
  // onBeforeDumpYaml
@@ -119,7 +148,7 @@ export class LpkBuild {
119
148
  this.beforeDumpYamlFn.push(fn);
120
149
  }
121
150
  // onBeforeTarContent
122
- // fn: function(contentdir) => void
151
+ // fn: function(contentdir, options) => void
123
152
  onBeforeTarContent(fn) {
124
153
  this.beforeTarContentFn.push(fn);
125
154
  }
@@ -146,7 +175,7 @@ export class LpkBuild {
146
175
  return this.manifest;
147
176
  }
148
177
 
149
- async exec(prefix = "") {
178
+ async exec() {
150
179
  if (this.beforeBuildPackageFn.length > 0) {
151
180
  this.options = await this.beforeBuildPackageFn.reduce(
152
181
  async (prev, curr) => {
@@ -168,62 +197,77 @@ export class LpkBuild {
168
197
  logger.warn("跳过执行 buildscript");
169
198
  }
170
199
 
200
+ // 输出路径
201
+ let packName = this.options["lpkPath"];
171
202
  const pkgout = path.resolve(this.pwd, this.options["pkgout"]);
172
- if (!isDirExist(pkgout)) {
203
+ if (!packName && !isDirExist(pkgout)) {
173
204
  throw `${pkgout} 不存在`;
174
205
  }
175
206
 
176
207
  const tempDir = fs.mkdtempSync(".lzc-cli-build");
177
-
178
208
  let contentdir = this.options["contentdir"];
179
- if (contentdir) {
180
- contentdir = path.isAbsolute(contentdir)
181
- ? contentdir
182
- : path.join(this.pwd, contentdir);
183
- if (!isDirExist(contentdir)) {
184
- throw `${contentdir} 不存在`;
209
+ try {
210
+ if (contentdir) {
211
+ contentdir = path.resolve(this.pwd, contentdir);
212
+ if (!isDirExist(contentdir)) {
213
+ throw `${contentdir} 不存在`;
214
+ }
215
+ } else {
216
+ logger.warn("跳过拷贝 contentdir 内容");
217
+ // 当没有指定的 contentdir 的时候,也生成一个空的文件夹
218
+ // 原因是:可能其他地方会复制内容进来,像 devshell 中的会在打包的时候,将ssh key拷贝进来
219
+ contentdir = fs.mkdtempSync(path.join(tempDir, "fake-contentdir"));
185
220
  }
186
- } else {
187
- logger.warn("跳过拷贝 contentdir 内容");
188
- // 当没有指定的 contentdir 的时候,也生成一个空的文件夹
189
- // 原因是:可能其他地方会复制内容进来,像 devshell 中的会在打包的时候,将ssh key拷贝进来
190
- contentdir = fs.mkdtempSync(path.join(tempDir, "fake-contentdir"));
191
- }
192
221
 
193
- // 开始打包 contentdir
194
- if (this.beforeTarContentFn.length > 0) {
195
- await this.beforeTarContentFn.reduce(async (prev, curr) => {
196
- let _prev = await prev;
197
- await curr(_prev);
198
- return _prev;
199
- }, contentdir);
200
- }
201
- tarContentDir("./", path.join(tempDir, "content.tar"), contentdir);
202
-
203
- // 开始生成 manifest.yml
204
- let manifest = await this.getManifest();
205
- if (this.beforeDumpYamlFn.length > 0) {
206
- manifest = await this.beforeDumpYamlFn.reduce(async (prev, curr) => {
207
- return await curr(await prev, this.options);
208
- }, manifest);
209
- }
210
- logger.debug("manifest\n", manifest);
211
- dumpToYaml(manifest, path.join(tempDir, "manifest.yml"));
212
-
213
- // 打包 lpk
214
- if (this.beforeDumpLpkFn.length > 0) {
215
- await this.beforeDumpLpkFn.reduce(async (prev, curr) => {
216
- await curr(this.options, this.pwd, tempDir);
217
- return prev;
218
- }, {});
219
- }
220
- const packName = `${prefix}${manifest.package}-v${manifest.version}.lpk`;
221
- const lpkPath = await archiveFolderTo(tempDir, path.join(pkgout, packName));
222
- logger.info(`输出lpk包 ${lpkPath.path}`);
222
+ // 开始打包 contentdir
223
+ if (this.beforeTarContentFn.length > 0) {
224
+ await this.beforeTarContentFn.reduce(async (prev, curr) => {
225
+ let _prev = await prev;
226
+ await curr(_prev, this.options);
227
+ return _prev;
228
+ }, contentdir);
229
+ }
230
+ tarContentDir("./", path.join(tempDir, "content.tar"), contentdir);
231
+
232
+ // 如果是临时的 contentdir, 目录在打包完成后删除
233
+ if (!this.options["contentdir"]) {
234
+ fs.rmSync(contentdir, { recursive: true });
235
+ }
223
236
 
224
- // remove temp file
225
- fs.rmSync(tempDir, { recursive: true });
237
+ // 开始生成 manifest.yml
238
+ let manifest = await this.getManifest();
239
+ if (process.env.LZC_VERSION) {
240
+ manifest.version = process.env.LZC_VERSION;
241
+ }
242
+ if (this.beforeDumpYamlFn.length > 0) {
243
+ manifest = await this.beforeDumpYamlFn.reduce(async (prev, curr) => {
244
+ return await curr(await prev, this.options);
245
+ }, manifest);
246
+ }
247
+ logger.debug("manifest\n", manifest);
248
+ dumpToYaml(manifest, path.join(tempDir, "manifest.yml"));
226
249
 
227
- return lpkPath.path;
250
+ // 打包 lpk
251
+ if (this.beforeDumpLpkFn.length > 0) {
252
+ await this.beforeDumpLpkFn.reduce(async (prev, curr) => {
253
+ await curr(this.options, this.pwd, tempDir);
254
+ return prev;
255
+ }, {});
256
+ }
257
+
258
+ if (!packName) {
259
+ packName = path.resolve(
260
+ pkgout,
261
+ `${manifest.package}-v${manifest.version}.lpk`
262
+ );
263
+ }
264
+
265
+ const lpkPath = await archiveFolderTo(tempDir, packName);
266
+ logger.info(`输出lpk包 ${lpkPath.path}`);
267
+
268
+ return lpkPath.path;
269
+ } finally {
270
+ fs.rmSync(tempDir, { recursive: true });
271
+ }
228
272
  }
229
273
  }