@lazycatcloud/lzc-cli 1.2.27 → 1.2.29

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 (37) hide show
  1. package/lib/app/apkshell.js +35 -0
  2. package/lib/app/index.js +89 -78
  3. package/lib/app/lpk_build.js +113 -117
  4. package/lib/app/lpk_create.js +78 -148
  5. package/lib/app/lpk_create_generator.js +103 -74
  6. package/lib/app/lpk_debug_bridge.js +61 -73
  7. package/lib/app/lpk_devshell.js +230 -229
  8. package/lib/app/lpk_devshell_docker.js +28 -28
  9. package/lib/app/lpk_installer.js +64 -49
  10. package/lib/appstore/index.js +29 -29
  11. package/lib/appstore/login.js +63 -68
  12. package/lib/appstore/prePublish.js +68 -68
  13. package/lib/appstore/publish.js +55 -55
  14. package/lib/box/index.js +25 -25
  15. package/lib/env.js +18 -18
  16. package/lib/shellapi.js +55 -58
  17. package/lib/utils.js +217 -164
  18. package/package.json +7 -1
  19. package/scripts/cli.js +56 -56
  20. package/template/_lpk/manifest.yml.in +8 -8
  21. package/template/vue/README.md +29 -0
  22. package/template/vue/index.html +13 -0
  23. package/template/vue/lzc-build.yml +59 -0
  24. package/template/vue/lzc-icon.png +0 -0
  25. package/template/vue/package.json +20 -0
  26. package/template/vue/public/vite.svg +1 -0
  27. package/template/vue/src/App.vue +30 -0
  28. package/template/vue/src/assets/vue.svg +1 -0
  29. package/template/vue/src/components/HelloWorld.vue +41 -0
  30. package/template/vue/src/main.ts +5 -0
  31. package/template/vue/src/style.css +79 -0
  32. package/template/vue/src/vite-env.d.ts +1 -0
  33. package/template/vue/tsconfig.app.json +24 -0
  34. package/template/vue/tsconfig.json +7 -0
  35. package/template/vue/tsconfig.node.json +22 -0
  36. package/template/vue/vite.config.ts +7 -0
  37. package/template/ionic_vue3/package-lock.json +0 -8100
@@ -1,10 +1,10 @@
1
1
  // lzc-cli app devshell
2
- import path from "node:path";
3
- import fs from "node:fs";
4
- import logger from "loglevel";
5
- import { execSync } from "node:child_process";
6
- import { LpkInstaller } from "./lpk_installer.js";
7
- import debounce from "lodash.debounce";
2
+ import path from "node:path"
3
+ import fs from "node:fs"
4
+ import logger from "loglevel"
5
+ import { execSync } from "node:child_process"
6
+ import { LpkInstaller } from "./lpk_installer.js"
7
+ import debounce from "lodash.debounce"
8
8
  import {
9
9
  mergeYamlInMemory,
10
10
  contextDirname,
@@ -18,15 +18,16 @@ import {
18
18
  isUserApp,
19
19
  createTemplateFileCommon,
20
20
  isDebugMode,
21
- resolveDomain
22
- } from "../utils.js";
23
- import os from "node:os";
24
- import commandExists from "command-exists";
25
- import chokidar from "chokidar";
26
- import _ from "lodash";
27
- import { DebugBridge } from "./lpk_debug_bridge.js";
28
- import shellApi from "../shellapi.js";
29
- import { collectContextFromDockerFile } from "./lpk_devshell_docker.js";
21
+ resolveDomain,
22
+ sleep
23
+ } from "../utils.js"
24
+ import os from "node:os"
25
+ import commandExists from "command-exists"
26
+ import chokidar from "chokidar"
27
+ import _ from "lodash"
28
+ import { DebugBridge } from "./lpk_debug_bridge.js"
29
+ import shellApi from "../shellapi.js"
30
+ import { collectContextFromDockerFile } from "./lpk_devshell_docker.js"
30
31
 
31
32
  // 判断是否需要重新构建
32
33
  // - 先判断 lzc-build.yml 是否发生改变
@@ -36,39 +37,39 @@ import { collectContextFromDockerFile } from "./lpk_devshell_docker.js";
36
37
  // - 根据在 backend api 中判断同步的目录下是否存在文件 判断当前运行的 app 是否已经有一个挂载的实例,避免重复挂载
37
38
  class AppDevShellMonitor {
38
39
  constructor(cwd, pkgId, buildConfigFile) {
39
- this.pwd = cwd ? path.resolve(cwd) : process.cwd();
40
- this.pkgId = pkgId;
40
+ this.pwd = cwd ? path.resolve(cwd) : process.cwd()
41
+ this.pkgId = pkgId
41
42
 
42
- this.optionsFilePath = path.join(this.pwd, buildConfigFile);
43
- this.options = loadFromYaml(this.optionsFilePath);
43
+ this.optionsFilePath = path.join(this.pwd, buildConfigFile)
44
+ this.options = loadFromYaml(this.optionsFilePath)
44
45
 
45
46
  this.manifestFilePath = this.options["manifest"]
46
47
  ? path.join(this.pwd, this.options["manifest"])
47
- : path.join(this.pwd, "lzc-manifest.yml");
48
+ : path.join(this.pwd, "lzc-manifest.yml")
48
49
 
49
50
  this.hashObject = {
50
51
  build: "",
51
- manifest: "",
52
- };
53
- this.cacheFilePath = undefined;
54
- this.oldHash = undefined;
55
- this.newHash = undefined;
56
- this.bridge = new DebugBridge();
52
+ manifest: ""
53
+ }
54
+ this.cacheFilePath = undefined
55
+ this.oldHash = undefined
56
+ this.newHash = undefined
57
+ this.bridge = new DebugBridge()
57
58
  }
58
59
 
59
60
  async init() {
60
- const pathId = await md5String(this.pwd);
61
+ const pathId = await md5String(this.pwd)
61
62
  this.cacheFilePath = path.resolve(
62
63
  os.tmpdir(),
63
64
  "lzc-cli-devshell",
64
65
  pathId,
65
66
  "hash"
66
- );
67
- ensureDir(this.cacheFilePath);
67
+ )
68
+ ensureDir(this.cacheFilePath)
68
69
 
69
- await this.updateHash();
70
+ await this.updateHash()
70
71
 
71
- return this;
72
+ return this
72
73
  }
73
74
 
74
75
  async shouldBuild() {
@@ -76,373 +77,376 @@ class AppDevShellMonitor {
76
77
  this.change() ||
77
78
  (await this.bridge.status(this.pkgId)) === "NotInstalled" ||
78
79
  !(await this.bridge.isDevshell(this.pkgId))
79
- );
80
+ )
80
81
  }
81
82
 
82
83
  change() {
83
- logger.debug("oldHash", this.oldHash);
84
- logger.debug("newHash", this.newHash);
85
- return !_.isEqual(this.oldHash, this.newHash);
84
+ logger.debug("oldHash", this.oldHash)
85
+ logger.debug("newHash", this.newHash)
86
+ return !_.isEqual(this.oldHash, this.newHash)
86
87
  }
87
88
 
88
89
  async updateHash() {
89
90
  this.oldHash = isFileExist(this.cacheFilePath)
90
91
  ? JSON.parse(fs.readFileSync(this.cacheFilePath))
91
- : {};
92
+ : {}
92
93
  const buildHash = isFileExist(this.optionsFilePath)
93
94
  ? await md5File(this.optionsFilePath)
94
- : "";
95
+ : ""
95
96
  const manifestHash = isFileExist(this.manifestFilePath)
96
97
  ? await md5File(this.manifestFilePath)
97
- : "";
98
+ : ""
98
99
  this.newHash = {
99
100
  build: buildHash,
100
- manifest: manifestHash,
101
- };
101
+ manifest: manifestHash
102
+ }
102
103
  if (!_.isEqual(this.oldHash, this.newHash)) {
103
- fs.writeFileSync(this.cacheFilePath, JSON.stringify(this.newHash));
104
+ fs.writeFileSync(this.cacheFilePath, JSON.stringify(this.newHash))
104
105
  }
105
106
  }
106
107
  }
107
108
 
108
109
  export class AppDevShell {
109
110
  constructor(cwd, lpkBuild, forceBuild, buildConfigFile) {
110
- this.cwd = cwd;
111
- this.lpkBuild = lpkBuild;
112
- this.forceBuild = forceBuild;
113
- this.buildConfigFile = buildConfigFile;
114
- this.isUserApp = false;
115
- this.monitor = undefined;
111
+ this.cwd = cwd
112
+ this.lpkBuild = lpkBuild
113
+ this.forceBuild = forceBuild
114
+ this.buildConfigFile = buildConfigFile
115
+ this.isUserApp = false
116
+ this.monitor = undefined
116
117
  }
117
118
 
118
119
  async init() {
119
- const manifest = await this.lpkBuild.getManifest();
120
+ const manifest = await this.lpkBuild.getManifest()
120
121
  this.monitor = await new AppDevShellMonitor(
121
122
  this.cwd,
122
123
  manifest["package"],
123
124
  this.buildConfigFile
124
- ).init();
125
- this.isUserApp = isUserApp(manifest);
125
+ ).init()
126
+ this.isUserApp = isUserApp(manifest)
126
127
  }
127
128
 
128
129
  async build() {
129
130
  // 先判断是否需要重新构建
130
131
  if (this.forceBuild || (await this.monitor.shouldBuild())) {
131
- logger.debug("build...");
132
- await this.devshellBuild();
132
+ logger.debug("build...")
133
+ await this.devshellBuild()
133
134
  }
134
135
  }
135
136
 
136
137
  async devshellBuild() {
137
138
  this.lpkBuild.onBeforeBuildPackage(async (options) => {
138
- const devshell = options["devshell"];
139
+ const devshell = options["devshell"]
139
140
  if (!devshell) {
140
- throw "devshell 模式下,devshell 字段必须要指定";
141
+ throw "devshell 模式下,devshell 字段必须要指定"
141
142
  }
142
143
 
143
- const routes = devshell["routes"];
144
+ const routes = devshell["routes"]
144
145
  if (!routes || routes.length == 0) {
145
- throw "devshell 模式下,必须要指定 routes 内容";
146
+ throw "devshell 模式下,必须要指定 routes 内容"
146
147
  }
147
148
 
148
- return options;
149
- });
149
+ return options
150
+ })
150
151
 
151
152
  // 复制 busybox 到 devshell 中去
152
153
  this.lpkBuild.onBeforeTarContent(async (contentdir) => {
153
154
  const busyboxPath = path.join(
154
155
  contextDirname(import.meta.url),
155
156
  "../../template/_lpk/busybox-1.35.0"
156
- );
157
- let dest = path.join(contentdir, "devshell", "busybox");
158
- ensureDir(dest);
159
- fs.copyFileSync(busyboxPath, dest);
160
- fs.chmodSync(dest, 0o775);
161
- });
157
+ )
158
+ let dest = path.join(contentdir, "devshell", "busybox")
159
+ ensureDir(dest)
160
+ fs.copyFileSync(busyboxPath, dest)
161
+ fs.chmodSync(dest, 0o775)
162
+ })
162
163
 
163
164
  // 复制 init_debug_bridge.sh 到 devshell 中去
164
165
  this.lpkBuild.onBeforeTarContent(async (contentdir) => {
165
166
  const initPath = path.join(
166
167
  contextDirname(import.meta.url),
167
168
  "../../template/_lpk/init_debug_bridge.sh"
168
- );
169
- let dest = path.join(contentdir, "devshell", "init_debug_bridge.sh");
170
- ensureDir(dest);
171
- fs.copyFileSync(initPath, dest);
172
- fs.chmodSync(dest, 0o775);
173
- });
169
+ )
170
+ let dest = path.join(contentdir, "devshell", "init_debug_bridge.sh")
171
+ ensureDir(dest)
172
+ fs.copyFileSync(initPath, dest)
173
+ fs.chmodSync(dest, 0o775)
174
+ })
174
175
 
175
176
  // 复制 exec.sh 到 devshell 中去
176
177
  this.lpkBuild.onBeforeTarContent(async (contentdir) => {
177
178
  const execScriptPath = path.join(
178
179
  contextDirname(import.meta.url),
179
180
  "../../template/_lpk/exec.sh"
180
- );
181
- let dest = path.join(contentdir, "devshell", "exec.sh");
182
- ensureDir(dest);
183
- fs.copyFileSync(execScriptPath, dest);
184
- fs.chmodSync(dest, 0o775);
185
- });
181
+ )
182
+ let dest = path.join(contentdir, "devshell", "exec.sh")
183
+ ensureDir(dest)
184
+ fs.copyFileSync(execScriptPath, dest)
185
+ fs.chmodSync(dest, 0o775)
186
+ })
186
187
 
187
188
  // 复制 setupscript 脚本
188
189
  this.lpkBuild.onBeforeTarContent(async (contentdir, options) => {
189
- const devshell = options["devshell"];
190
+ const devshell = options["devshell"]
190
191
  if (!devshell["setupscript"]) {
191
- return;
192
+ return
192
193
  }
193
194
 
194
- logger.debug("处理 setupscript ");
195
- const dest = path.join(contentdir, "devshell", "setupscript");
196
- ensureDir(dest);
195
+ logger.debug("处理 setupscript ")
196
+ const dest = path.join(contentdir, "devshell", "setupscript")
197
+ ensureDir(dest)
197
198
 
198
199
  // 先判断是否文件
199
- const filePath = path.resolve(devshell["setupscript"]);
200
+ const filePath = path.resolve(devshell["setupscript"])
200
201
  if (isFileExist(filePath)) {
201
- fs.copyFileSync(filePath, dest);
202
+ fs.copyFileSync(filePath, dest)
202
203
  } else {
203
- fs.writeFileSync(
204
- dest,
205
- `#!/bin/sh\nset -ex\n${devshell["setupscript"]}`
206
- );
204
+ fs.writeFileSync(dest, `#!/bin/sh\nset -ex\n${devshell["setupscript"]}`)
207
205
  }
208
- fs.chmodSync(dest, 0o775);
209
- });
206
+ fs.chmodSync(dest, 0o775)
207
+ })
210
208
 
211
209
  // 在生成 manifest.yml 之前合并 devshell manifest 模板字段
212
210
  this.lpkBuild.onBeforeDumpYaml(async (manifest, options) => {
213
- logger.debug("merge lzc-build.yml devshell routes field");
214
- const devshell = options["devshell"];
211
+ logger.debug("merge lzc-build.yml devshell routes field")
212
+ const devshell = options["devshell"]
215
213
 
216
- const routes = devshell["routes"];
217
- logger.debug("options devshell delete 'routes' field");
218
- delete options["devshell"]["routes"];
214
+ const routes = devshell["routes"]
215
+ logger.debug("options devshell delete 'routes' field")
216
+ delete options["devshell"]["routes"]
219
217
 
220
218
  // 添加 devshell 必要路由
221
219
  routes.push(
222
220
  "/__debug.bridge=exec://80,/lzcapp/pkg/content/devshell/init_debug_bridge.sh"
223
- );
224
- routes.push("/__isdevshell=file:///lzcapp/pkg/devshell");
221
+ )
222
+ routes.push("/__isdevshell=file:///lzcapp/pkg/devshell")
225
223
 
226
224
  // 如果 devshell 中的 router 和 manifest 中的 prefix 出现冲突
227
225
  // 优先使用 devshell 中的。
228
226
  routes.forEach((r) => {
229
227
  if (!r) {
230
- return;
228
+ return
231
229
  }
232
230
 
233
- let prefix = r.split("=")[0];
231
+ let prefix = r.split("=")[0]
234
232
  let index = manifest["application"]["routes"].findIndex((mr) => {
235
233
  if (!mr) {
236
- return false;
234
+ return false
237
235
  }
238
- return mr.split("=")[0] == prefix;
239
- });
236
+ return mr.split("=")[0] == prefix
237
+ })
240
238
  if (index > -1) {
241
- manifest["application"]["routes"].splice(index, 1);
239
+ manifest["application"]["routes"].splice(index, 1)
242
240
  }
243
- });
244
- const application = { routes };
245
- return mergeYamlInMemory([manifest, { application }]);
246
- });
241
+ })
242
+ const application = { routes }
243
+ return mergeYamlInMemory([manifest, { application }])
244
+ })
247
245
 
248
246
  // 在生成 manifest.yml 之前合并 lzc-build.yml devshell 字段的值
249
247
  // 并加上 health_check 字段, 当处于 devshell 的情况时,禁用 health_check
250
248
  // 避免应用永远处于 unhealth 导致状态卡在 starting
251
249
  this.lpkBuild.onBeforeDumpYaml(async (manifest, options) => {
252
- logger.debug("merge lzc-build.yml devshell services\n", options);
253
- const userapp = this.isUserApp ? shellApi.uid + "." : "";
250
+ logger.debug("merge lzc-build.yml devshell services\n", options)
251
+ const userapp = this.isUserApp ? shellApi.uid + "." : ""
254
252
  const devshell = {
255
253
  application: {
256
254
  devshell: options["devshell"],
257
255
  health_check: {
258
256
  test_url: `http://${userapp}app.${manifest["package"]}.lzcapp/__isdevshell`,
259
- disable: true,
260
- },
261
- },
262
- };
263
- return mergeYamlInMemory([manifest, devshell]);
264
- });
257
+ disable: true
258
+ }
259
+ }
260
+ }
261
+ return mergeYamlInMemory([manifest, devshell])
262
+ })
265
263
 
266
264
  // 如果 services/devshell 中有 dependencies 字段,优先使用
267
265
  this.lpkBuild.onBeforeDumpYaml(async (manifest) => {
268
- const config = manifest["application"]["devshell"];
266
+ const config = manifest["application"]["devshell"]
269
267
  if (!config || !config["dependencies"]) {
270
- return manifest;
268
+ return manifest
271
269
  }
272
270
 
273
- const deps = config["dependencies"];
271
+ const deps = config["dependencies"]
274
272
  if (deps.length == 0) {
275
- logger.warn("dependencies 内容为空,跳过 dependencies");
276
- delete manifest["application"]["devshell"]["dependencies"];
277
- return manifest;
273
+ logger.warn("dependencies 内容为空,跳过 dependencies")
274
+ delete manifest["application"]["devshell"]["dependencies"]
275
+ return manifest
278
276
  }
279
277
 
280
- const depsStr = deps.sort().join(" ");
281
- logger.debug("开始创建 Dockerfile 文件");
278
+ const depsStr = deps.sort().join(" ")
279
+ logger.debug("开始创建 Dockerfile 文件")
282
280
 
283
- const tempDir = fs.mkdtempSync(".lzc-cli-build-dependencies");
281
+ const tempDir = fs.mkdtempSync(".lzc-cli-build-dependencies")
284
282
  try {
285
283
  const dockerfilePath = path.join(
286
284
  contextDirname(import.meta.url),
287
285
  "../../template/_lpk/Dockerfile.in"
288
- );
286
+ )
289
287
  await createTemplateFileCommon(
290
288
  dockerfilePath,
291
289
  path.join(tempDir, "Dockerfile"),
292
290
  { dependencies: depsStr }
293
- );
291
+ )
294
292
 
295
- const label = `${await md5String(depsStr)}:latest`;
296
- logger.debug(`开始在盒子中构建 ${label} 镜像 from ${tempDir}`);
293
+ const label = `${await md5String(depsStr)}:latest`
294
+ logger.debug(`开始在盒子中构建 ${label} 镜像 from ${tempDir}`)
297
295
 
298
296
  const contextTar = await collectContextFromDockerFile(
299
297
  tempDir,
300
298
  path.resolve(tempDir, "Dockerfile")
301
- );
302
- const bridge = new DebugBridge();
303
- const tag = await bridge.buildImage(label, contextTar);
304
- delete manifest["application"]["devshell"];
305
- manifest["application"]["image"] = tag;
299
+ )
300
+ const bridge = new DebugBridge()
301
+ const tag = await bridge.buildImage(label, contextTar)
302
+ delete manifest["application"]["devshell"]
303
+ manifest["application"]["image"] = tag
306
304
  } finally {
307
- fs.rmSync(tempDir, { recursive: true });
305
+ fs.rmSync(tempDir, { recursive: true })
308
306
  }
309
- return manifest;
310
- });
307
+ return manifest
308
+ })
311
309
 
312
310
  // 如果 services 中有 devshell 的字段,需要检测是否需要提前构建
313
311
  this.lpkBuild.onBeforeDumpYaml(async (manifest) => {
314
- const application = manifest["application"];
312
+ const application = manifest["application"]
315
313
  if (!application || !application["devshell"]) {
316
- return manifest;
314
+ return manifest
317
315
  }
318
316
 
319
- const config = manifest["application"]["devshell"];
317
+ const config = manifest["application"]["devshell"]
320
318
  if (!config || !config["build"]) {
321
- return manifest;
319
+ return manifest
322
320
  }
323
321
 
324
- const label = `${manifest["package"]}-devshell:${manifest["version"]}`;
325
- logger.debug(`开始在盒子中构建 ${label} 镜像`);
322
+ const label = `${manifest["package"]}-devshell:${manifest["version"]}`
323
+ logger.debug(`开始在盒子中构建 ${label} 镜像`)
326
324
 
327
325
  const contextTar = await collectContextFromDockerFile(
328
326
  process.cwd(),
329
327
  path.resolve(process.cwd(), config["build"], "Dockerfile")
330
- );
328
+ )
331
329
 
332
- const bridge = new DebugBridge();
333
- const tag = await bridge.buildImage(label, contextTar);
334
- delete manifest["application"]["devshell"];
335
- manifest["application"]["image"] = tag;
336
- return manifest;
337
- });
330
+ const bridge = new DebugBridge()
331
+ const tag = await bridge.buildImage(label, contextTar)
332
+ delete manifest["application"]["devshell"]
333
+ manifest["application"]["image"] = tag
334
+ return manifest
335
+ })
338
336
 
339
337
  // 如果 devshell 中指定了 image 字段将使用 image 字段
340
338
  this.lpkBuild.onBeforeDumpYaml(async (manifest) => {
341
- const config = manifest["application"];
339
+ const config = manifest["application"]
342
340
  if (config["devshell"] && config["devshell"]["image"]) {
343
- manifest["application"]["image"] = config["devshell"]["image"];
344
- delete manifest["application"]["devshell"];
341
+ manifest["application"]["image"] = config["devshell"]["image"]
342
+ delete manifest["application"]["devshell"]
345
343
  }
346
- return manifest;
347
- });
344
+ return manifest
345
+ })
348
346
 
349
347
  // 如果没有找到 devshell 中没有指定 image 不存在,将默认使用的 lzc-cli/devshell 容器
350
348
  this.lpkBuild.onBeforeDumpYaml(async (manifest) => {
351
- delete manifest["application"]["devshell"];
349
+ delete manifest["application"]["devshell"]
352
350
 
353
- const config = manifest["application"];
351
+ const config = manifest["application"]
354
352
  if (config["image"]) {
355
- return manifest;
353
+ return manifest
356
354
  }
357
355
 
358
- logger.debug("use default lzc-cli/devshell image");
359
- manifest["application"][
360
- "image"
361
- ] = `registry.lazycat.cloud/lzc-cli/devshell:v0.0.5`;
362
- return manifest;
363
- });
356
+ logger.debug("use default lzc-cli/devshell image")
357
+ manifest["application"]["image"] =
358
+ `registry.lazycat.cloud/lzc-cli/devshell:v0.0.5`
359
+ return manifest
360
+ })
364
361
 
365
362
  // 添加一个 devshell 的标记在 lpk 中,标记当前 lpk 为一个 debug 版本
366
363
  this.lpkBuild.onBeforeDumpLpk(async (options, cwd, destDir) => {
367
- fs.writeFileSync(path.resolve(destDir, "devshell"), "");
368
- });
364
+ fs.writeFileSync(path.resolve(destDir, "devshell"), "")
365
+ })
369
366
 
370
367
  // 在构建生成 lpk 包后,调用 deploy 进行部署
371
- let installer = new LpkInstaller();
372
- await installer.init();
373
- await installer.deploy(this.lpkBuild, true);
368
+ let installer = new LpkInstaller()
369
+ await installer.init()
370
+ await installer.deploy(this.lpkBuild, true)
374
371
  }
375
372
 
376
373
  async rsyncShell() {
377
- const manifest = await this.lpkBuild.getManifest();
378
- const pkgId = manifest["package"];
374
+ const manifest = await this.lpkBuild.getManifest()
375
+ const pkgId = manifest["package"]
379
376
 
380
- let isSync = false;
377
+ let isSync = false
381
378
  try {
382
- const locker = new FileLocker(pkgId);
383
- locker.lock();
379
+ const locker = new FileLocker(pkgId)
380
+ locker.lock()
384
381
  process.on("exit", () => {
385
- logger.debug("filelock unlock");
386
- locker.unlock();
387
- });
388
- isSync = true;
382
+ logger.debug("filelock unlock")
383
+ locker.unlock()
384
+ })
385
+ isSync = true
389
386
  } catch (err) {
390
- logger.debug("filelock catch");
391
- logger.debug(err);
387
+ logger.debug("filelock catch")
388
+ logger.debug(err)
392
389
  }
393
390
 
394
- const devshell = new DevShell(pkgId, this.isUserApp);
391
+ const devshell = new DevShell(pkgId, this.isUserApp)
395
392
  if (isSync) {
396
- await devshell.shell();
393
+ await devshell.shell()
397
394
  } else {
398
- await devshell.connectShell();
395
+ await devshell.connectShell()
399
396
  }
400
- logger.debug("exit shell");
397
+ logger.debug("exit shell")
401
398
  // TODO: shell 在正常情况下,按 Ctrl-D 就会退出,回到原来的本地的 shell ,但
402
399
  // 现在会一直卡在退出状态后,必须要另外手动的指定 pkill node
403
- process.exit(0);
400
+ process.exit(0)
404
401
  }
405
402
  }
406
403
 
407
404
  class DevShell {
408
405
  constructor(appId, isUserApp) {
409
- this.appId = appId;
410
- this.isUserApp = isUserApp;
406
+ this.appId = appId
407
+ this.isUserApp = isUserApp
411
408
  }
412
409
 
413
410
  async syncProject(appId) {
414
411
  // prettier-ignore
415
- const resolvedIp = await resolveDomain(this.domain);
412
+ const resolvedIp = await resolveDomain(`dev.${shellApi.boxname}.heiyu.space`);
416
413
  let rsh = [
417
414
  "ssh",
418
- "-J", `box@${resolvedIp}:22222`,
419
- "-p", `22222`,
420
- "-o", `"StrictHostKeyChecking=no"`,
421
- "-o", `"UserKnownHostsFile=/dev/null"`,
422
- "-o", `"ConnectionAttempts=3"`,
423
- "-o", `"ConnectTimeout=30"`,
424
- "-o", `${isDebugMode() ? '"LogLevel=DEBUG"' :'"LogLevel=ERROR"'}`,
425
- ].join(" ");
415
+ "-J",
416
+ `box@[${resolvedIp}]:22222`,
417
+ "-p",
418
+ `22222`,
419
+ "-o",
420
+ `"StrictHostKeyChecking=no"`,
421
+ "-o",
422
+ `"UserKnownHostsFile=/dev/null"`,
423
+ "-o",
424
+ `"ConnectionAttempts=3"`,
425
+ "-o",
426
+ `"ConnectTimeout=30"`,
427
+ "-o",
428
+ `${isDebugMode() ? '"LogLevel=DEBUG"' : '"LogLevel=ERROR"'}`
429
+ ].join(" ")
426
430
  // 检查rsync工具是否存在:提示用户
427
- const rsyncExisted = commandExists.sync("rsync");
431
+ const rsyncExisted = commandExists.sync("rsync")
428
432
  if (!rsyncExisted) {
429
- logger.error("请检查 rsync 是否安装,路径是否正确!");
430
- process.exit(1);
433
+ logger.error("请检查 rsync 是否安装,路径是否正确!")
434
+ process.exit(1)
431
435
  }
432
436
 
433
- const rsyncDebug = isDebugMode() ? "-P" : "";
437
+ const rsyncDebug = isDebugMode() ? "-P" : ""
434
438
  const host = this.isUserApp
435
439
  ? `${shellApi.uid}.app.${appId}.lzcapp`
436
- : `app.${appId}.lzcapp`;
437
- const dest = `root@${host}:/lzcapp/cache/devshell`;
440
+ : `app.${appId}.lzcapp`
441
+ const dest = `root@${host}:/lzcapp/cache/devshell`
438
442
  try {
439
443
  execSync(
440
444
  `rsync ${rsyncDebug} --rsh='${rsh}' --recursive --relative --perms --update -F --filter=':- .gitignore' --ignore-errors . ${dest}`,
441
445
  { stdio: ["ignore", "inherit", "inherit"] }
442
- );
446
+ )
443
447
  } catch (err) {
444
- logger.error("rsync 同步失败");
445
- logger.debug(err);
448
+ logger.error("rsync 同步失败")
449
+ logger.debug(err)
446
450
  }
447
451
  }
448
452
 
@@ -452,77 +456,74 @@ class DevShell {
452
456
  // fs.watch 虽然不支持递归,但可以直接监听整个文件夹的变动
453
457
  async fallbackWatch(filepath, gitignore, callback) {
454
458
  if (gitignore.contain(filepath)) {
455
- return Promise.resolve();
459
+ return Promise.resolve()
456
460
  }
457
461
 
458
462
  if (filepath.endsWith(".git") || filepath.endsWith(".lazycat")) {
459
- return Promise.resolve();
463
+ return Promise.resolve()
460
464
  }
461
465
 
462
- fs.watch(filepath, callback(filepath));
466
+ fs.watch(filepath, callback(filepath))
463
467
 
464
468
  // 如果为一个文件夹,则扫描当中是否含有子文件夹
465
469
  if (isDirSync(filepath)) {
466
470
  return gitignore.readdir(filepath, (err, files) => {
467
471
  if (err) {
468
- throw err;
472
+ throw err
469
473
  }
470
474
 
471
475
  if (files.length <= 0) {
472
- return;
476
+ return
473
477
  }
474
478
 
475
479
  files.forEach((f) => {
476
480
  if (f.isDirectory()) {
477
- this.fallbackWatch(
478
- path.join(filepath, f.name),
479
- gitignore,
480
- callback
481
- );
481
+ this.fallbackWatch(path.join(filepath, f.name), gitignore, callback)
482
482
  }
483
- });
484
- });
483
+ })
484
+ })
485
485
  }
486
486
  }
487
487
 
488
488
  // 监听非.gitignore文件
489
489
  // TODO: 目前仅仅监听process.cwd()以下的文件
490
490
  async watchFile(appId) {
491
- const ignore = new GitIgnore(process.cwd());
492
- await ignore.collect();
491
+ const ignore = new GitIgnore(process.cwd())
492
+ await ignore.collect()
493
493
  chokidar
494
494
  .watch(".", {
495
495
  ignored: (path) => {
496
- if ([".git", ".lazycat"].some((p) => path.startsWith(p))) return true;
496
+ if ([".git", ".lazycat"].some((p) => path.startsWith(p))) return true
497
497
 
498
- return ignore.contain(path);
498
+ return ignore.contain(path)
499
499
  },
500
- ignoreInitial: true,
500
+ ignoreInitial: true
501
501
  })
502
502
  .on(
503
503
  "all",
504
504
  debounce(() => {
505
- this.syncProject(appId);
505
+ this.syncProject(appId)
506
506
  }, 1000)
507
- );
507
+ )
508
508
  }
509
509
 
510
510
  async shell() {
511
511
  try {
512
512
  // 监听文件
513
- await this.watchFile(this.appId);
513
+ await this.watchFile(this.appId)
514
514
  await this.connectShell(async () => {
515
515
  // 在连接成功的时候,同步一次文件
516
- await this.syncProject(this.appId);
517
- });
516
+ await sleep(300)
517
+ await this.syncProject(this.appId)
518
+ })
518
519
  } catch (e) {
519
- console.log(e);
520
- return Promise.reject(e);
520
+ console.log(e)
521
+ return Promise.reject(e)
521
522
  }
522
523
  }
523
524
 
524
525
  async connectShell(onconnect = null) {
525
- const bridge = new DebugBridge();
526
- await bridge.devshell(this.appId, this.isUserApp, onconnect);
526
+ const bridge = new DebugBridge()
527
+ await bridge.devshell(this.appId, this.isUserApp, onconnect)
527
528
  }
528
529
  }