@lazycatcloud/lzc-cli 1.2.29 → 1.2.31

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,6 +1,6 @@
1
1
  import fs from "node:fs"
2
- import fetch from "node-fetch"
3
2
  import logger from "loglevel"
3
+ import { api } from "../utils.js"
4
4
 
5
5
  export async function triggerApk(id, name, iconPath) {
6
6
  if (!id) {
@@ -15,12 +15,9 @@ export async function triggerApk(id, name, iconPath) {
15
15
  if (iconPath) {
16
16
  form.append("app_icon", new Blob([fs.readFileSync(iconPath)]))
17
17
  }
18
- const resp = await fetch(
18
+ const resp = await api.post(
19
19
  "https://appstore.lazycat.cloud/api/trigger_latest_for_app",
20
- {
21
- method: "POST",
22
- body: form
23
- }
20
+ form
24
21
  )
25
22
  if (resp.status == 304) {
26
23
  } else if (resp.status == 201) {
package/lib/app/index.js CHANGED
@@ -7,13 +7,23 @@ import logger from "loglevel"
7
7
  import { sleep } from "../utils.js"
8
8
  import { DebugBridge } from "./lpk_debug_bridge.js"
9
9
  import shellApi from "../shellapi.js"
10
+ import { generate } from "./lpk_create_generator.js"
10
11
 
11
12
  export function lpkProjectCommand(program) {
12
13
  let subCommands = [
14
+ {
15
+ command: "init",
16
+ desc: "初始化懒猫云应用(提供最基础的模板)",
17
+ handler: async () => {
18
+ generate("blank", "./")
19
+ logger.info("应用初始化完成")
20
+ }
21
+ },
13
22
  {
14
23
  command: "create <name>",
15
24
  desc: "创建懒猫云应用",
16
25
  handler: async ({ name }) => {
26
+ name = String(name)
17
27
  await lpkCreate(name)
18
28
  }
19
29
  },
@@ -52,14 +52,13 @@ export class LpkManifest {
52
52
  {
53
53
  type: "input",
54
54
  name: "appId",
55
- message: `请输入应用ID, 如(${this.defaultAppID})`,
55
+ message: `请输入应用ID,例如app-demo1`,
56
56
  default: this.defaultAppID,
57
57
  validate: (input) => {
58
58
  if (isValidAppId(input)) {
59
59
  return true
60
60
  } else {
61
- // return `请输入 1-63 位的字母、数字或-,且不能以-开头或结尾。`
62
- return `请输入 1-63 位的字母、数字。`
61
+ return `允许小写字母或数字或-的组合,但不以数字开头,且不能以 - 开头或结束,也不能有连续的短横线 --`
63
62
  }
64
63
  }
65
64
  }
@@ -50,7 +50,7 @@ function writeFileTree(target, files) {
50
50
  })
51
51
  }
52
52
 
53
- async function generate(type, to, opts = {}) {
53
+ export async function generate(type, to, opts = {}) {
54
54
  const files = await loadFiles(type, opts.prefix)
55
55
  writeFileTree(to, files)
56
56
  }
@@ -2,7 +2,8 @@ import { spawn, spawnSync } from "child_process"
2
2
  import fs from "node:fs"
3
3
  import shellApi from "../shellapi.js"
4
4
  import inquirer from "inquirer"
5
- import { isDebugMode, resolveDomain } from "../utils.js"
5
+ import { isDebugMode, resolveDomain, sleep } from "../utils.js"
6
+ import logger from "loglevel"
6
7
 
7
8
  export class DebugBridge {
8
9
  constructor() {
@@ -85,6 +86,16 @@ export class DebugBridge {
85
86
 
86
87
  async devshell(appId, isUserApp, onconnect = null) {
87
88
  const resolvedIp = await resolveDomain(this.domain)
89
+ let waiting = true
90
+ while (waiting) {
91
+ if (await this.isDevshell(appId)) {
92
+ waiting = false
93
+ break
94
+ }
95
+ logger.debug("wait app container to running...")
96
+ await sleep(100)
97
+ }
98
+
88
99
  const stream = spawn(
89
100
  `ssh -p 22222 box@${resolvedIp}`,
90
101
  [
@@ -104,9 +115,9 @@ export class DebugBridge {
104
115
  stream.on("close", (code) => {
105
116
  code == 0 ? resolve() : reject()
106
117
  })
107
- if (onconnect) {
108
- stream.on("spawn", onconnect)
109
- }
118
+ // spawn 事件只是进程启动成功的事件,并不是ssh成功连接上的事件。所以这里使
119
+ // 用前面的一个 isDevshell 判断是否已经启动这个容器,再使用 spawn
120
+ stream.on("spawn", onconnect)
110
121
  })
111
122
  }
112
123
 
@@ -513,7 +513,6 @@ class DevShell {
513
513
  await this.watchFile(this.appId)
514
514
  await this.connectShell(async () => {
515
515
  // 在连接成功的时候,同步一次文件
516
- await sleep(300)
517
516
  await this.syncProject(this.appId)
518
517
  })
519
518
  } catch (e) {
package/lib/shellapi.js CHANGED
@@ -32,6 +32,11 @@ class ShellApi {
32
32
  const { addr, cred } = this.readShellApiInfo()
33
33
  this.client = new pbShell.ShellCore(addr, grpc.credentials.createInsecure())
34
34
 
35
+ // 检查当前 shell 环境上下文是否配置 HTTP_PROXY
36
+ if (this.checkEnvProxy()) {
37
+ logger.warn(`WARN:: 当前终端环境已配置 HTTP_PROXY 代理,可能会导致访问懒猫微服失败,如果未影响功能可以忽略该警告`)
38
+ }
39
+
35
40
  const md = new grpc.Metadata()
36
41
  md.add("lzc-shellapi-cred", cred)
37
42
  this.metadata = md
@@ -115,6 +120,19 @@ class ShellApi {
115
120
  })
116
121
  }
117
122
 
123
+ checkEnvProxy() {
124
+ if(process.env.HTTPS_PROXY ||
125
+ process.env.HTTP_PROXY ||
126
+ process.env.ALL_PROXY ||
127
+ process.env.https_proxy ||
128
+ process.env.http_proxy ||
129
+ process.env.all_proxy
130
+ ){
131
+ return true
132
+ }
133
+ return false
134
+ }
135
+
118
136
  async setDefaultBox(boxname) {
119
137
  const boxes = await this.boxList()
120
138
  const box = boxes.find((b) => b.box_name === boxname)
package/lib/utils.js CHANGED
@@ -16,6 +16,21 @@ import { spawnSync } from "node:child_process"
16
16
  import logger from "loglevel"
17
17
  import * as tar from "tar"
18
18
  import dns from "node:dns/promises"
19
+ import axios from "axios"
20
+
21
+ // 创建 Axios 实例
22
+ export const api = axios.create()
23
+
24
+ // 添加响应拦截器
25
+ api.interceptors.response.use(
26
+ (response) => response, // 直接返回响应
27
+ (error) => {
28
+ if (error.response && error.response.status === 304) {
29
+ return Promise.resolve(error.response) // 返回响应以便后续处理
30
+ }
31
+ return Promise.reject(error) // 其他错误继续抛出
32
+ }
33
+ )
19
34
 
20
35
  export const envsubstr = async (templateContents, args) => {
21
36
  const parse = await importDefault("envsub/js/envsub-parser.js")
@@ -344,16 +359,15 @@ export class FileLocker {
344
359
  }
345
360
 
346
361
  export function isValidAppId(appId) {
347
- // 暂时去掉 - 的支持
348
- // const regex = new RegExp("^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$")
349
- const regex = new RegExp("^[a-z][a-z0-9]{0,61}[a-zA-Z0-9]$")
362
+ const regex = new RegExp("^(?!-)(?!.*--)[a-z][a-z0-9]*([-][a-z0-9]+)*$")
350
363
  return regex.test(appId)
351
364
  }
352
365
 
353
366
  export function isValidPackageName(packageName) {
354
367
  // 暂时去掉 - 的支持
355
- // const regex = new RegExp("^(?:[a-z][a-z0-9-]*\\.)+[a-z][a-z0-9-]*$")
356
- const regex = new RegExp("^(?:[a-z][a-z0-9]*\\.)+[a-z][a-z0-9]*$")
368
+ const regex = new RegExp(
369
+ "^[a-z][a-z0-9]*([-][a-z0-9]+)*(?:.[a-z][a-z0-9]*([-][a-z0-9]+)*)*$"
370
+ )
357
371
  return regex.test(packageName)
358
372
  }
359
373
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lazycatcloud/lzc-cli",
3
- "version": "1.2.29",
3
+ "version": "1.2.31",
4
4
  "description": "lazycat cloud developer kit",
5
5
  "files": [
6
6
  "template",
@@ -21,6 +21,7 @@
21
21
  "@grpc/grpc-js": "^1.11.1",
22
22
  "@grpc/proto-loader": "^0.7.13",
23
23
  "archiver": "^7.0.1",
24
+ "axios": "^1.7.7",
24
25
  "chalk": "^5.3.0",
25
26
  "chokidar": "^3.6.0",
26
27
  "command-exists": "^1.2.9",
@@ -0,0 +1,59 @@
1
+ # 整个文件中,可以通过 ${var} 的方式,使用 manifest 字段指定的文件定义的值
2
+
3
+ # buildscript
4
+ # - 可以为构建脚本的路径地址
5
+ # - 如果构建命令简单,也可以直接写 sh 的命令
6
+ buildscript: npm run build
7
+
8
+ # manifest: 指定 lpk 包的 manifest.yml 文件路径
9
+ manifest: ./lzc-manifest.yml
10
+
11
+ # contentdir: 指定打包的内容,将会打包到 lpk 中
12
+ contentdir: ./dist
13
+
14
+ # pkgout: lpk 包的输出路径
15
+ pkgout: ./
16
+
17
+ # icon 指定 lpk 包 icon 的路径路径,如果不指定将会警告
18
+ # icon 仅仅允许 png 后缀的文件
19
+ icon: ./lzc-icon.png
20
+
21
+ # devshell 自定义应用的开发容器环境
22
+ # - routers 指定应用容器的访问路由
23
+
24
+ # devshell 没有指定 image 的情况,将会默认使用 registry.lazycat.cloud/lzc-cli/devshell:v0.0.5
25
+ # devshell:
26
+ # routers:
27
+ # - /=http://127.0.0.1:8080
28
+
29
+ # devshell 指定 image 的情况
30
+ # devshell:
31
+ # routes:
32
+ # - /=http://127.0.0.1:3000
33
+ # image: registry.lazycat.cloud/lzc-cli/devshell:v0.0.5
34
+
35
+ # devshell 指定构建Dockerfile
36
+ # image 字段如果没有定义,将默认使用 ${package}-devshell:${version}
37
+ # devshell:
38
+ # routes:
39
+ # - /=http://127.0.0.1:3000
40
+ # image: ${package}-devshell:${version}
41
+ # pull_policy: build
42
+ # build: .
43
+
44
+ # dvshell 指定开发依赖的情况
45
+ # 这种情况下,选用 alpine:latest 作为基础镜像,在 dependencies 中添加所需要的开发依赖即可
46
+ # 如果 dependencies 和 build 同时存在,将会优先使用 dependencies
47
+ devshell:
48
+ routes:
49
+ - /=http://127.0.0.1:3000
50
+ dependencies:
51
+ - nodejs
52
+ - npm
53
+ # setupscript 每次进入到app container后都会执行的配置脚本
54
+ # - 可以为脚本的路径地址
55
+ # - 如果构建命令简单,也可以直接写 sh 的命令
56
+ # setupscript: export GOPROXY=https://goproxy.cn
57
+ # setupscript: ./setupscript.sh
58
+ setupscript: |
59
+ export npm_config_registry=https://registry.npmmirror.com
Binary file
@@ -0,0 +1,12 @@
1
+ lzc-sdk-version: 0.1
2
+ name: helloworld
3
+ package: cloud.lazycat.app.helloworld
4
+ version: 0.0.1
5
+ description:
6
+ license: https://choosealicense.com/licenses/mit/
7
+ homepage:
8
+ author:
9
+ application:
10
+ subdomain: helloworld
11
+ routes:
12
+ - /=file:///lzcapp/pkg/content/dist