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