@lazycatcloud/lzc-cli 1.3.13 → 2.0.0-pre.0

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 (104) hide show
  1. package/README.md +30 -5
  2. package/changelog.md +16 -0
  3. package/lib/app/index.js +174 -58
  4. package/lib/app/lpk_build.js +197 -18
  5. package/lib/app/lpk_build_images.js +728 -0
  6. package/lib/app/lpk_create.js +96 -23
  7. package/lib/app/lpk_create_generator.js +150 -12
  8. package/lib/app/lpk_devshell.js +35 -21
  9. package/lib/app/lpk_embed_images.js +257 -0
  10. package/lib/app/lpk_installer.js +15 -7
  11. package/lib/app/project_cp.js +64 -0
  12. package/lib/app/project_deploy.js +33 -0
  13. package/lib/app/project_exec.js +45 -0
  14. package/lib/app/project_info.js +106 -0
  15. package/lib/app/project_log.js +67 -0
  16. package/lib/app/project_runtime.js +261 -0
  17. package/lib/app/project_start.js +100 -0
  18. package/lib/appstore/index.js +56 -16
  19. package/lib/appstore/publish.js +16 -13
  20. package/lib/box/index.js +103 -6
  21. package/lib/box/ssh_remote.js +259 -0
  22. package/lib/build_remote.js +22 -0
  23. package/lib/config/index.js +4 -3
  24. package/lib/debug_bridge.js +837 -44
  25. package/lib/docker/index.js +30 -10
  26. package/lib/i18n/index.js +1 -0
  27. package/lib/i18n/locales/en/translation.json +263 -250
  28. package/lib/i18n/locales/zh/translation.json +57 -44
  29. package/lib/lpk/core.js +487 -0
  30. package/lib/lpk/index.js +210 -0
  31. package/lib/shellapi.js +5 -5
  32. package/lib/sig/core.js +254 -0
  33. package/lib/sig/index.js +88 -0
  34. package/lib/utils.js +17 -12
  35. package/package.json +4 -3
  36. package/scripts/cli.js +4 -0
  37. package/template/_lpk/README.md +11 -3
  38. package/template/_lpk/gui-vnc.manifest.yml.in +27 -0
  39. package/template/_lpk/manifest.yml.in +4 -2
  40. package/template/_lpk/todolist-golang.manifest.yml.in +16 -0
  41. package/template/_lpk/todolist-java.manifest.yml.in +15 -0
  42. package/template/_lpk/todolist-python.manifest.yml.in +15 -0
  43. package/template/_lpk/vue.lzc-build.yml.in +0 -44
  44. package/template/blank/_gitignore +1 -0
  45. package/template/blank/lzc-build.yml +25 -40
  46. package/template/blank/lzc-manifest.yml +14 -7
  47. package/template/golang/Dockerfile +19 -0
  48. package/template/golang/README.md +33 -0
  49. package/template/golang/_gitignore +3 -0
  50. package/template/golang/go.mod +3 -0
  51. package/template/golang/lzc-build.yml +21 -0
  52. package/template/golang/lzc-icon.png +0 -0
  53. package/template/golang/main.go +252 -0
  54. package/template/golang/run.sh +3 -0
  55. package/template/golang/web/index.html +238 -0
  56. package/template/gui-vnc/README.md +19 -0
  57. package/template/gui-vnc/_gitignore +2 -0
  58. package/template/gui-vnc/images/Dockerfile +30 -0
  59. package/template/gui-vnc/images/kasmvnc.yaml +33 -0
  60. package/template/gui-vnc/images/startup-script.desktop +9 -0
  61. package/template/gui-vnc/images/startup-script.sh +6 -0
  62. package/template/gui-vnc/lzc-build.yml +23 -0
  63. package/template/gui-vnc/lzc-icon.png +0 -0
  64. package/template/python/Dockerfile +15 -0
  65. package/template/python/README.md +33 -0
  66. package/template/python/_gitignore +3 -0
  67. package/template/python/app.py +110 -0
  68. package/template/python/lzc-build.yml +21 -0
  69. package/template/python/lzc-icon.png +0 -0
  70. package/template/python/requirements.txt +1 -0
  71. package/template/python/run.sh +3 -0
  72. package/template/python/web/index.html +238 -0
  73. package/template/springboot/Dockerfile +20 -0
  74. package/template/springboot/README.md +33 -0
  75. package/template/springboot/_gitignore +3 -0
  76. package/template/springboot/lzc-build.yml +21 -0
  77. package/template/springboot/lzc-icon.png +0 -0
  78. package/template/springboot/pom.xml +38 -0
  79. package/template/springboot/run.sh +3 -0
  80. package/template/springboot/src/main/java/cloud/lazycat/app/Application.java +132 -0
  81. package/template/springboot/src/main/resources/application.properties +1 -0
  82. package/template/springboot/src/main/resources/static/index.html +238 -0
  83. package/template/vue/README.md +17 -7
  84. package/template/vue/_gitignore +1 -0
  85. package/template/vue/lzc-build.yml +31 -42
  86. package/template/vue/src/App.vue +36 -25
  87. package/template/vue/src/style.css +106 -49
  88. package/template/vue-minidb/README.md +34 -0
  89. package/template/vue-minidb/_gitignore +26 -0
  90. package/template/vue-minidb/index.html +13 -0
  91. package/template/vue-minidb/lzc-build.yml +48 -0
  92. package/template/vue-minidb/lzc-icon.png +0 -0
  93. package/template/vue-minidb/package.json +21 -0
  94. package/template/vue-minidb/public/vite.svg +1 -0
  95. package/template/vue-minidb/src/App.vue +206 -0
  96. package/template/vue-minidb/src/assets/vue.svg +1 -0
  97. package/template/vue-minidb/src/main.ts +5 -0
  98. package/template/vue-minidb/src/style.css +136 -0
  99. package/template/vue-minidb/src/vite-env.d.ts +1 -0
  100. package/template/vue-minidb/tsconfig.app.json +24 -0
  101. package/template/vue-minidb/tsconfig.json +7 -0
  102. package/template/vue-minidb/tsconfig.node.json +22 -0
  103. package/template/vue-minidb/vite.config.ts +10 -0
  104. /package/template/{vue → vue-minidb}/src/components/HelloWorld.vue +0 -0
package/README.md CHANGED
@@ -17,19 +17,44 @@ lzc-cli completion >> ~/.zshrc
17
17
  下面开始使用 `lzc-cli` 去创建一个项目吧!
18
18
 
19
19
  ```bash
20
+ # 在新目录创建项目(交互选择模板)
20
21
  lzc-cli project create you_project
21
22
 
22
- # 构建懒猫云平台lpk包
23
- lzc-cli project build
23
+ # 在当前目录初始化空白项目
24
+ lzc-cli project create --in-place
25
+
26
+ # 构建 release lpk 包(优先 lzc-build.release.yml,不存在则回退 lzc-build.yml)
27
+ lzc-cli project release
24
28
 
25
29
  # 将lpk包安装到盒子中去
26
- lzc-cli app install
30
+ lzc-cli lpk install
31
+
32
+ # 部署后默认自动启动
33
+ lzc-cli project deploy
27
34
 
28
- # 使用 devshell 可以让你在盒子中开发调试
29
- lzc-cli project devshell
35
+ # 进入运行容器调试
36
+ lzc-cli project exec /bin/sh
30
37
 
31
38
  # 经过测试后,将包发布到懒猫云商店中去
32
39
  lzc-cli appstore publish
33
40
  ```
34
41
 
35
42
  [changelog](./changelog.md)
43
+
44
+ #### box add-by-ssh 远端直连模式
45
+
46
+ 当运行环境无法使用 `hclient` 时,可通过 `box add-by-ssh` 配置远端 ssh 目标,由 `lzc-cli` 直连 `lzcos ssh` 并在远端执行 debug bridge 命令。
47
+
48
+ 示例:
49
+
50
+ ```bash
51
+ lzc-cli box add-by-ssh root 192.168.31.13
52
+ ```
53
+
54
+ 说明:
55
+
56
+ 1. 参数格式为 `loginUser address`,地址支持 `host` 或 `host:port`
57
+ 2. 配置后会自动设为默认盒子,可通过 `box list/switch/default` 管理
58
+ 3. `project release/deploy/start/exec/cp/log/info`、`lpk install/uninstall`、`docker/docker-compose` 都会优先使用该远端
59
+ 4. `lzc-build.yml` 不再支持 `remote` 字段
60
+ 5. 可选基础配置文件为 `lzc-build.base.yml`(与构建配置同目录)
package/changelog.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.0.0-pre.0
4
+
5
+ 1. Add lpkv2 features for internal testing
6
+
7
+ ## [1.3.14](https://gitee.com/linakesi/lzc-cli/compare/v1.3.13...v1.3.14) (2025-12-17)
8
+
9
+
10
+ ### Bug Fixes
11
+
12
+ * dealing with the i18n difference escape problem ([2b98cdf](https://gitee.com/linakesi/lzc-cli/commits/2b98cdf0573a1537bee409079d6160da1b7cd80b))
13
+
14
+
15
+ ### Features
16
+
17
+ * cmd publish add `changelog-files` option ([17d95c6](https://gitee.com/linakesi/lzc-cli/commits/17d95c6fa761f25af234946dedd3d6a0503ba962))
18
+
3
19
  ## [1.3.13](https://gitee.com/linakesi/lzc-cli/compare/v1.3.12...v1.3.13) (2025-12-10)
4
20
 
5
21
 
package/lib/app/index.js CHANGED
@@ -1,7 +1,13 @@
1
1
  import path from 'node:path';
2
- import lpkCreate from './lpk_create.js';
2
+ import lpkCreate, { listProjectTemplateValues, normalizeTemplateType } from './lpk_create.js';
3
3
  import { LpkBuild } from './lpk_build.js';
4
4
  import { AppDevShell } from './lpk_devshell.js';
5
+ import { projectExecCommand } from './project_exec.js';
6
+ import { projectCpCommand } from './project_cp.js';
7
+ import { projectLogCommand } from './project_log.js';
8
+ import { projectInfoCommand } from './project_info.js';
9
+ import { projectStartCommand } from './project_start.js';
10
+ import { projectDeployCommand } from './project_deploy.js';
5
11
  import { LpkInstaller, installConfig } from './lpk_installer.js';
6
12
  import logger from 'loglevel';
7
13
  import { sleep, checkRsync } from '../utils.js';
@@ -9,28 +15,110 @@ import { DebugBridge } from '../debug_bridge.js';
9
15
  import shellApi from '../shellapi.js';
10
16
  import { generate } from './lpk_create_generator.js';
11
17
  import { t } from '../i18n/index.js';
18
+ import { resolveBuildRemoteFromFile } from '../build_remote.js';
19
+ import { resolveProjectReleaseConfigPath } from './project_runtime.js';
20
+
21
+ async function installLpk(pkgPath, apk) {
22
+ if (!resolveBuildRemoteFromFile(process.cwd())) {
23
+ await shellApi.init();
24
+ }
25
+ installConfig.apk = apk == 'y';
26
+
27
+ const installPath = pkgPath ?? process.cwd();
28
+ const installer = new LpkInstaller();
29
+ await installer.init();
30
+ await installer.install(installPath);
31
+ }
32
+
33
+ async function uninstallLpk(pkgId, deleteData) {
34
+ const buildRemote = resolveBuildRemoteFromFile(process.cwd());
35
+ if (!buildRemote) {
36
+ await shellApi.init();
37
+ }
38
+
39
+ const bridge = new DebugBridge(process.cwd(), buildRemote);
40
+ await bridge.init();
41
+ await bridge.uninstall(pkgId, deleteData);
42
+ logger.debug(`default lcmd device: ${bridge.boxname} , uninstall the app ${pkgId} finish`);
43
+ }
44
+
45
+ function lpkInstallSubCommand({ desc }) {
46
+ return {
47
+ command: 'install [pkgPath]',
48
+ desc,
49
+ builder: (args) => {
50
+ args.option('apk', {
51
+ describe: t('lzc_cli.lib.app.index.lpk_cmd_index_rags_apk_desc', '是否生成APK(y/n)'),
52
+ type: 'string',
53
+ default: 'y',
54
+ });
55
+ },
56
+ handler: async ({ pkgPath, apk }) => {
57
+ await installLpk(pkgPath, apk);
58
+ },
59
+ };
60
+ }
61
+
62
+ function lpkUninstallSubCommand({ desc }) {
63
+ return {
64
+ command: 'uninstall <pkgId>',
65
+ desc,
66
+ builder: (args) => {
67
+ args.option('delete-data', {
68
+ describe: t('lzc_cli.lib.app.index.lpk_cmd_uninstall_rags_delete_data_desc', '删除应用数据 ⚠️ 警告: 应用数据删除后无法恢复'),
69
+ type: 'boolean',
70
+ default: false,
71
+ });
72
+ },
73
+ handler: async ({ pkgId, deleteData }) => {
74
+ await uninstallLpk(pkgId, deleteData);
75
+ },
76
+ };
77
+ }
12
78
 
13
79
  export function lpkProjectCommand(program) {
14
80
  let subCommands = [
15
81
  {
16
- command: 'init',
17
- desc: t('lzc_cli.lib.app.index.lpk_cmd_init_desc', '初始化懒猫云应用(提供最基础的模板)'),
18
- handler: async () => {
19
- generate('blank', './');
20
- logger.info(t('lzc_cli.lib.app.index.lpk_cmd_init_success', '应用初始化完成'));
21
- },
22
- },
23
- {
24
- command: 'create <name>',
82
+ command: 'create [name]',
25
83
  desc: t('lzc_cli.lib.app.index.lpk_cmd_create_desc', '创建懒猫云应用'),
26
- handler: async ({ name }) => {
27
- name = String(name);
28
- await lpkCreate(name);
84
+ builder: (args) => {
85
+ args.option('in-place', {
86
+ describe: 'Initialize current directory with blank template',
87
+ type: 'boolean',
88
+ default: false,
89
+ });
90
+ args.option('t', {
91
+ alias: 'template',
92
+ describe: `Template name (${listProjectTemplateValues().join(', ')})`,
93
+ type: 'string',
94
+ });
95
+ },
96
+ handler: async ({ name, inPlace, template }) => {
97
+ if (name && inPlace) {
98
+ throw new Error('--in-place cannot be used with <name>.');
99
+ }
100
+ const normalizedTemplate = normalizeTemplateType(template);
101
+ if (name) {
102
+ name = String(name);
103
+ await lpkCreate(name, process.cwd(), normalizedTemplate);
104
+ return;
105
+ }
106
+
107
+ if (inPlace) {
108
+ if (normalizedTemplate) {
109
+ throw new Error('--template cannot be used with --in-place.');
110
+ }
111
+ generate('blank', './');
112
+ logger.info(t('lzc_cli.lib.app.index.lpk_cmd_init_success', '应用初始化完成'));
113
+ return;
114
+ }
115
+
116
+ throw new Error('Project name is required unless --in-place is used.');
29
117
  },
30
118
  },
31
119
  {
32
120
  command: 'build [context]',
33
- desc: t('lzc_cli.lib.app.index.lpk_cmd_build_desc', '构建'),
121
+ desc: false,
34
122
  builder: (args) => {
35
123
  args.option('o', {
36
124
  alias: 'output',
@@ -58,9 +146,41 @@ export function lpkProjectCommand(program) {
58
146
  await lpk.exec();
59
147
  },
60
148
  },
149
+ {
150
+ command: 'release [context]',
151
+ desc: 'Build release package',
152
+ builder: (args) => {
153
+ args.option('o', {
154
+ alias: 'output',
155
+ describe: t('lzc_cli.lib.app.index.lpk_cmd_build_args_output_desc', '输出文件'),
156
+ type: 'string',
157
+ });
158
+ args.option('f', {
159
+ alias: 'file',
160
+ describe: t('lzc_cli.lib.app.index.lpk_cmd_build_args_file_desc', '指定构建的lzc-build.yml文件'),
161
+ type: 'string',
162
+ });
163
+ },
164
+ handler: async ({ context, output, file }) => {
165
+ const cwd = context ? path.resolve(context) : process.cwd();
166
+ const configPath = resolveProjectReleaseConfigPath(cwd, file);
167
+ const projectCwd = path.dirname(configPath);
168
+ const configName = path.basename(configPath);
169
+ const lpk = await new LpkBuild(projectCwd, configName).init();
170
+ lpk.onBeforeBuildPackage(async (options) => {
171
+ delete options['devshell'];
172
+
173
+ if (output) {
174
+ options['lpkPath'] = output;
175
+ }
176
+ return options;
177
+ });
178
+ await lpk.exec();
179
+ },
180
+ },
61
181
  {
62
182
  command: 'devshell [context]',
63
- desc: t('lzc_cli.lib.app.index.lpk_cmd_devshell_desc', '进入盒子的开发环境'),
183
+ desc: false,
64
184
  builder: (args) => {
65
185
  args.option('f', {
66
186
  alias: 'force',
@@ -84,12 +204,16 @@ export function lpkProjectCommand(program) {
84
204
  });
85
205
  },
86
206
  handler: async ({ context, force, config, contentdir, apk }) => {
87
- await shellApi.init();
207
+ logger.warn('project devshell is deprecated. Use "project deploy", "project start", "project exec", "project cp", and "project log" instead.');
208
+ const cwd = context ? path.resolve(context) : process.cwd();
209
+ const buildRemote = resolveBuildRemoteFromFile(cwd, config);
210
+ if (!buildRemote) {
211
+ await shellApi.init();
212
+ }
88
213
  // 检测 rsync 满足
89
214
  await checkRsync();
90
215
 
91
216
  installConfig.apk = apk == 'y';
92
- const cwd = context ? path.resolve(context) : process.cwd();
93
217
  const lpkBuild = await new LpkBuild(cwd, config).init();
94
218
  lpkBuild.onBeforeBuildPackage(async (options) => {
95
219
  // devshell 正常情况下,不需要执行 buildscript 和 contentdir 字段
@@ -109,6 +233,26 @@ export function lpkProjectCommand(program) {
109
233
  await app.rsyncShell();
110
234
  },
111
235
  },
236
+ {
237
+ command: 'app',
238
+ desc: false,
239
+ builder: (args) => {
240
+ args.command([
241
+ lpkInstallSubCommand({
242
+ desc: false,
243
+ }),
244
+ lpkUninstallSubCommand({
245
+ desc: false,
246
+ }),
247
+ ]);
248
+ },
249
+ },
250
+ projectExecCommand(),
251
+ projectCpCommand(),
252
+ projectLogCommand(),
253
+ projectInfoCommand(),
254
+ projectStartCommand(),
255
+ projectDeployCommand(),
112
256
  ];
113
257
  program.command({
114
258
  command: 'project',
@@ -121,52 +265,22 @@ export function lpkProjectCommand(program) {
121
265
 
122
266
  export function lpkAppCommand(program) {
123
267
  let subCommands = [
124
- {
125
- command: 'install [pkgPath]',
268
+ lpkInstallSubCommand({
126
269
  desc: t('lzc_cli.lib.app.index.lpk_cmd_install_desc', '部署应用至设备, pkgPath 可以为路径,或者https://,http://请求地址, 如果不填写,将默认为当前目录下的lpk'),
127
- builder: (args) => {
128
- args.option('apk', {
129
- describe: t('lzc_cli.lib.app.index.lpk_cmd_index_rags_apk_desc', '是否生成APK(y/n)'),
130
- type: 'string',
131
- default: 'y',
132
- });
133
- },
134
- handler: async ({ pkgPath, apk }) => {
135
- await shellApi.init();
136
- installConfig.apk = apk == 'y';
137
-
138
- pkgPath = pkgPath ?? process.cwd();
139
- const installer = new LpkInstaller();
140
- await installer.init();
141
- await installer.install(pkgPath);
142
- },
143
- },
144
- {
145
- command: 'uninstall <pkgId>',
270
+ }),
271
+ lpkUninstallSubCommand({
146
272
  desc: t('lzc_cli.lib.app.index.lpk_cmd_uninstall_desc', '从设备中卸载某一个应用'),
147
- builder: (args) => {
148
- args.option('delete-data', {
149
- describe: t('lzc_cli.lib.app.index.lpk_cmd_uninstall_rags_delete_data_desc', '删除应用数据 ⚠️ 警告: 应用数据删除后无法恢复'),
150
- type: 'boolean',
151
- default: false,
152
- });
153
- },
154
- handler: async ({ pkgId, deleteData }) => {
155
- await shellApi.init();
156
-
157
- const bridge = new DebugBridge();
158
- await bridge.init();
159
- await bridge.uninstall(pkgId, deleteData);
160
- logger.debug(`default lcmd device: ${bridge.boxname} , uninstall the app ${pkgId} finish`);
161
- },
162
- },
273
+ }),
163
274
  {
164
275
  command: 'status <pkgId>',
165
276
  desc: t('lzc_cli.lib.app.index.lpk_cmd_status_desc', '获取某一个应用的状态'),
166
277
  handler: async ({ pkgId }) => {
167
- await shellApi.init();
278
+ const buildRemote = resolveBuildRemoteFromFile(process.cwd());
279
+ if (!buildRemote) {
280
+ await shellApi.init();
281
+ }
168
282
 
169
- const bridge = new DebugBridge();
283
+ const bridge = new DebugBridge(process.cwd(), buildRemote);
170
284
  await bridge.init();
171
285
  const status = await bridge.status(pkgId);
172
286
  console.log(status);
@@ -184,7 +298,9 @@ export function lpkAppCommand(program) {
184
298
  });
185
299
  },
186
300
  handler: async () => {
187
- await shellApi.init();
301
+ if (!resolveBuildRemoteFromFile(process.cwd())) {
302
+ await shellApi.init();
303
+ }
188
304
 
189
305
  throw 'not yet realized';
190
306
  },
@@ -192,7 +308,7 @@ export function lpkAppCommand(program) {
192
308
  ];
193
309
  program.command({
194
310
  command: 'app',
195
- desc: t('lzc_cli.lib.app.index.lpk_cmd_app_desc', '应用管理'),
311
+ desc: false,
196
312
  builder: async (args) => {
197
313
  args.command(subCommands);
198
314
  },