@lazycatcloud/lzc-cli 1.1.5 → 1.1.8
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.
- package/cmds/app.js +1 -5
- package/cmds/dev.js +11 -5
- package/lib/api.js +24 -7
- package/lib/app/index.js +93 -0
- package/lib/app/lpk_build.js +241 -0
- package/lib/app/lpk_create.js +201 -0
- package/lib/app/lpk_devshell.js +621 -0
- package/lib/app/lpk_installer.js +67 -0
- package/lib/appstore/login.js +134 -0
- package/lib/archiver.js +0 -42
- package/lib/autologin.js +82 -0
- package/lib/box/check_qemu.js +39 -16
- package/lib/box/hportal.js +7 -1
- package/lib/box/index.js +8 -7
- package/lib/box/qemu_vm_mgr.js +12 -11
- package/lib/dev.js +0 -4
- package/lib/env.js +16 -49
- package/lib/generator.js +2 -2
- package/lib/sdk.js +5 -6
- package/lib/utils.js +66 -144
- package/package.json +8 -3
- package/scripts/cli.js +91 -12
- package/template/_lazycat/debug/shell/Dockerfile +5 -3
- package/template/_lazycat/debug/shell/docker-compose.override.yml.in +2 -12
- package/template/_lazycat/debug/shell/entrypoint.sh +3 -1
- package/template/_lpk/Dockerfile.in +8 -0
- package/template/_lpk/devshell/Dockerfile +18 -0
- package/template/_lpk/devshell/build.sh +5 -0
- package/template/_lpk/devshell/entrypoint.sh +8 -0
- package/template/_lpk/devshell/sshd_config +117 -0
- package/template/_lpk/manifest.yml.in +17 -0
- package/template/_lpk/sync/Dockerfile +16 -0
- package/template/_lpk/sync/build.sh +5 -0
- package/template/_lpk/sync/entrypoint.sh +8 -0
- package/template/_lpk/sync/sshd_config +117 -0
- package/template/_lpk/sync.manifest.yml.in +3 -0
- package/template/golang/build.sh +6 -0
- package/template/golang/lzc-build.yml +52 -0
- package/template/ionic_vue3/lzc-build.yml +53 -0
- package/template/ionic_vue3/vite.config.ts +1 -1
- package/template/release/golang/build.sh +1 -1
- package/template/release/ionic_vue3/Dockerfile +1 -1
- package/template/release/ionic_vue3/build.sh +1 -3
- package/template/release/ionic_vue3/docker-compose.yml.in +0 -5
- package/template/release/vue/Dockerfile +1 -1
- package/template/release/vue/build.sh +2 -3
- package/template/release/vue/docker-compose.yml.in +0 -5
- package/template/vue/lzc-build.yml +53 -0
- package/template/vue/src/main.js +3 -14
- package/template/vue/vue.config.js +2 -1
- package/template/_lazycat/debug/shell/nginx.conf.template +0 -64
- package/template/vue/src/lzc.js +0 -110
package/lib/sdk.js
CHANGED
|
@@ -4,8 +4,8 @@ import Docker from "dockerode";
|
|
|
4
4
|
import process from "process";
|
|
5
5
|
import fs from "fs";
|
|
6
6
|
import { Client } from "ssh2";
|
|
7
|
-
import chalk from "chalk";
|
|
8
7
|
import Key from "./key.js";
|
|
8
|
+
import logger from "loglevel";
|
|
9
9
|
|
|
10
10
|
export async function connectOptions(host) {
|
|
11
11
|
const pairs = await new Key().getKeyPair();
|
|
@@ -38,7 +38,7 @@ export class DockerClient {
|
|
|
38
38
|
async init() {
|
|
39
39
|
this.docker = !!this.host
|
|
40
40
|
? new Docker({
|
|
41
|
-
protocal: "
|
|
41
|
+
protocal: "ssh",
|
|
42
42
|
agent: ssh(await connectOptions(this.host)),
|
|
43
43
|
})
|
|
44
44
|
: new Docker();
|
|
@@ -47,9 +47,7 @@ export class DockerClient {
|
|
|
47
47
|
|
|
48
48
|
async function onUncaughtException(e) {
|
|
49
49
|
if (e.code == "ECONNREFUSED") {
|
|
50
|
-
|
|
51
|
-
chalk.red(`无法连接 sdk 服务, 请确保 ${chalk.yellow(host)} 可以访问`)
|
|
52
|
-
);
|
|
50
|
+
logger.error(`无法连接 sdk 服务, 请确保 ${host} 可以访问`);
|
|
53
51
|
process.exit(1);
|
|
54
52
|
} else {
|
|
55
53
|
throw e;
|
|
@@ -78,6 +76,7 @@ export class SSHClient {
|
|
|
78
76
|
this.con
|
|
79
77
|
.on("ready", () => resolve(this.con))
|
|
80
78
|
.on("error", (err) => {
|
|
79
|
+
logger.error("ssh client ", err);
|
|
81
80
|
reject(err);
|
|
82
81
|
})
|
|
83
82
|
.on("close", () => resolve(null))
|
|
@@ -126,7 +125,7 @@ export class SSHClient {
|
|
|
126
125
|
}
|
|
127
126
|
|
|
128
127
|
export async function dockerPullLzcAppsImage(host) {
|
|
129
|
-
|
|
128
|
+
logger.warn("* 更新lzcapp镜像, 未来可能会移除此操作");
|
|
130
129
|
const opts = await connectOptions(host);
|
|
131
130
|
const client = new SSHClient(opts);
|
|
132
131
|
await client.connect();
|
package/lib/utils.js
CHANGED
|
@@ -8,13 +8,14 @@ import glob from "fast-glob";
|
|
|
8
8
|
import yaml from "js-yaml";
|
|
9
9
|
import mergeWith from "lodash.mergewith";
|
|
10
10
|
import isArray from "lodash.isarray";
|
|
11
|
-
import
|
|
11
|
+
import { request } from "./autologin.js";
|
|
12
12
|
import { dirname } from "path";
|
|
13
13
|
import { fileURLToPath } from "url";
|
|
14
14
|
import ignore from "ignore";
|
|
15
15
|
import ora from "ora";
|
|
16
16
|
import { desireStatusTimer } from "../lib/api.js";
|
|
17
17
|
import { warn } from "console";
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
18
19
|
|
|
19
20
|
const META_MARK = "x-lazycat-app";
|
|
20
21
|
const APP_FOLDER = ".lazycat";
|
|
@@ -26,103 +27,6 @@ export const envsubstr = async (templateContents, args) => {
|
|
|
26
27
|
const parse = await importDefault("envsub/js/envsub-parser.js");
|
|
27
28
|
return parse(templateContents, args);
|
|
28
29
|
};
|
|
29
|
-
/**
|
|
30
|
-
* 为盒子安装SDK应用
|
|
31
|
-
* @param box_url 盒子入口地址
|
|
32
|
-
**/
|
|
33
|
-
async function InstallSDK(box_url) {
|
|
34
|
-
try {
|
|
35
|
-
let url = `${box_url}/api/app/apply?id=sdk`;
|
|
36
|
-
const resp = await fetch(url, { method: "post" });
|
|
37
|
-
if (resp.status != 200) {
|
|
38
|
-
throw new Error(
|
|
39
|
-
chalk.red(
|
|
40
|
-
`无法安装, 请确保 ${chalk.yellow(
|
|
41
|
-
new URL(url).origin
|
|
42
|
-
)} 可以访问或者在应用商店安装 sdk`
|
|
43
|
-
)
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
} catch (err) {
|
|
47
|
-
throw err;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* 检查SDK安装部署的状态
|
|
52
|
-
* @param box_url 盒子入口地址
|
|
53
|
-
**/
|
|
54
|
-
async function checkSDKInstallStatus(box_url) {
|
|
55
|
-
const checkSDKstatus = async function (box_url) {
|
|
56
|
-
let url = `${box_url}/api/app/status?id=sdk`;
|
|
57
|
-
const resp = await fetch(url);
|
|
58
|
-
if (resp.status == 200) {
|
|
59
|
-
const status = await resp.json();
|
|
60
|
-
return status;
|
|
61
|
-
} else {
|
|
62
|
-
let text = await resp.text();
|
|
63
|
-
throw text;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
const spinner = ora().start();
|
|
67
|
-
let { status, info } = await checkSDKstatus(box_url);
|
|
68
|
-
spinner.text = "部署进度";
|
|
69
|
-
switch (status) {
|
|
70
|
-
case "running":
|
|
71
|
-
console.log(chalk.yellow("应用正在运行中"));
|
|
72
|
-
break;
|
|
73
|
-
case "error":
|
|
74
|
-
spinner.stop();
|
|
75
|
-
console.log(status, info);
|
|
76
|
-
throw info.msg;
|
|
77
|
-
default:
|
|
78
|
-
try {
|
|
79
|
-
await desireStatusTimer(
|
|
80
|
-
(result) => {
|
|
81
|
-
spinner.text = "部署进度 " + result.status;
|
|
82
|
-
return result.status === "running";
|
|
83
|
-
},
|
|
84
|
-
() => {
|
|
85
|
-
return checkSDKstatus(box_url);
|
|
86
|
-
}
|
|
87
|
-
);
|
|
88
|
-
} catch (error) {
|
|
89
|
-
throw error;
|
|
90
|
-
} finally {
|
|
91
|
-
spinner.stop();
|
|
92
|
-
}
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
spinner.stop();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* 获取所有已安装的app
|
|
100
|
-
* @param box_url 盒子入口地址
|
|
101
|
-
**/
|
|
102
|
-
async function getInstalledApps(box_url) {
|
|
103
|
-
try {
|
|
104
|
-
let url = `${box_url}/api/app/dump`;
|
|
105
|
-
const resp = await fetch(url);
|
|
106
|
-
if (resp.status != 200) throw new Error(chalk.red("获取所有已安装App失败"));
|
|
107
|
-
return await resp.json();
|
|
108
|
-
} catch (e) {
|
|
109
|
-
console.log(e);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* 查找某个app是否已安装]
|
|
114
|
-
* @param box_url 盒子入口地址
|
|
115
|
-
* @param app_id app名
|
|
116
|
-
* */
|
|
117
|
-
async function findAppIsInstalled(box_url, app_id) {
|
|
118
|
-
const apps = await getInstalledApps(box_url);
|
|
119
|
-
for (let app in apps) {
|
|
120
|
-
if (app == app_id) {
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
30
|
|
|
127
31
|
/**
|
|
128
32
|
* 确保文件夹存在
|
|
@@ -191,9 +95,10 @@ function findAppRootPath(aPath) {
|
|
|
191
95
|
|
|
192
96
|
function toPair(object) {
|
|
193
97
|
return Object.keys(object).map((key) => {
|
|
98
|
+
let value = object[key] ? object[key].toString() : "";
|
|
194
99
|
return {
|
|
195
100
|
name: key,
|
|
196
|
-
value
|
|
101
|
+
value,
|
|
197
102
|
};
|
|
198
103
|
});
|
|
199
104
|
}
|
|
@@ -203,43 +108,14 @@ function getMetaInfo(composeFile) {
|
|
|
203
108
|
return doc[META_MARK];
|
|
204
109
|
}
|
|
205
110
|
|
|
206
|
-
async function
|
|
111
|
+
async function envTemplateFile(templateFile, env) {
|
|
207
112
|
const template = yaml.load(fs.readFileSync(templateFile, "utf8"));
|
|
208
|
-
// const meta = template[META_MARK];
|
|
209
|
-
// if (
|
|
210
|
-
// meta &&
|
|
211
|
-
// Array.isArray(meta["permissions"]) &&
|
|
212
|
-
// meta["permissions"].includes("lzcapis")
|
|
213
|
-
// ) {
|
|
214
|
-
// template[META_MARK]["ingress"].push({
|
|
215
|
-
// service: "lazycat-apis-sidecar",
|
|
216
|
-
// port: 8888,
|
|
217
|
-
// subdomain: "${APP_NAME}",
|
|
218
|
-
// path: "/lzcapis/",
|
|
219
|
-
// auth: "oidc",
|
|
220
|
-
// authcallback: "/lzcapis/oidc-callback",
|
|
221
|
-
// });
|
|
222
|
-
// template["services"]["lazycat-apis-sidecar"] = {
|
|
223
|
-
// image: "registry.lazycat.cloud/lazycat-apis-sidecar",
|
|
224
|
-
// // volumes_from: ["${APP_NAME}:rw"],
|
|
225
|
-
// volumes: ["lzcapis-lzcapp:/lzcapp"],
|
|
226
|
-
// command: [
|
|
227
|
-
// "--client-id=${LAZYCAT_AUTH_OIDC_CLIENT_ID}",
|
|
228
|
-
// "--client-secret=${LAZYCAT_AUTH_OIDC_CLIENT_SECRET}",
|
|
229
|
-
// "--client-url=https://${LAZYCAT_APP_ORIGIN}/lzcapis/",
|
|
230
|
-
// "--issuer=${LAZYCAT_AUTH_OIDC_ISSUER_URL}",
|
|
231
|
-
// "--prefix=lzcapis",
|
|
232
|
-
// "--fs-root=/lzcapp/documents",
|
|
233
|
-
// ],
|
|
234
|
-
// };
|
|
235
|
-
// }
|
|
236
|
-
//
|
|
237
113
|
const options = {
|
|
238
114
|
envs: toPair(env),
|
|
239
115
|
syntax: "default",
|
|
240
116
|
protect: false,
|
|
241
117
|
};
|
|
242
|
-
|
|
118
|
+
return await envsubstr(
|
|
243
119
|
yaml.dump(template, {
|
|
244
120
|
styles: {
|
|
245
121
|
"!!null": "empty", // dump null as ""
|
|
@@ -247,7 +123,23 @@ async function createTemplateFile(templateFile, outputFile, env) {
|
|
|
247
123
|
}),
|
|
248
124
|
{ options }
|
|
249
125
|
);
|
|
126
|
+
}
|
|
250
127
|
|
|
128
|
+
async function createTemplateFile(templateFile, outputFile, env) {
|
|
129
|
+
let output = await envTemplateFile(templateFile, env);
|
|
130
|
+
fs.writeFileSync(outputFile, output);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function createTemplateFileCommon(templateFile, outputFile, env) {
|
|
134
|
+
const template = yaml.load(fs.readFileSync(templateFile, "utf8"));
|
|
135
|
+
const options = {
|
|
136
|
+
envs: toPair(env),
|
|
137
|
+
syntax: "default",
|
|
138
|
+
protect: false,
|
|
139
|
+
};
|
|
140
|
+
const output = await envsubstr(fs.readFileSync(templateFile, "utf-8"), {
|
|
141
|
+
options,
|
|
142
|
+
});
|
|
251
143
|
fs.writeFileSync(outputFile, output);
|
|
252
144
|
}
|
|
253
145
|
|
|
@@ -262,7 +154,7 @@ async function copyDotAppDir(from, to, opts = {}) {
|
|
|
262
154
|
if (fs.existsSync(to)) {
|
|
263
155
|
fs.rmSync(to, { recursive: true });
|
|
264
156
|
}
|
|
265
|
-
const _files = await glob(["
|
|
157
|
+
const _files = await glob(["**"].concat(include), {
|
|
266
158
|
cwd: from,
|
|
267
159
|
dot: true,
|
|
268
160
|
ignore: ignore,
|
|
@@ -289,6 +181,22 @@ async function copyDotAppDir(from, to, opts = {}) {
|
|
|
289
181
|
}
|
|
290
182
|
}
|
|
291
183
|
|
|
184
|
+
function mergeYamlInMemory(args) {
|
|
185
|
+
if (args.length == 0) {
|
|
186
|
+
return {};
|
|
187
|
+
} else if (args.length == 1) {
|
|
188
|
+
return args[0];
|
|
189
|
+
}
|
|
190
|
+
return args.reduce((prev, curr) => {
|
|
191
|
+
let result = mergeWith(prev, curr, (objValue, srcValue) => {
|
|
192
|
+
if (isArray(objValue)) {
|
|
193
|
+
return objValue.concat(srcValue);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
return result;
|
|
197
|
+
}, {});
|
|
198
|
+
}
|
|
199
|
+
|
|
292
200
|
// override yaml, notice this will change target file
|
|
293
201
|
function mergeYaml(target, source) {
|
|
294
202
|
const targetContent = yaml.load(fs.readFileSync(target, "utf8"));
|
|
@@ -302,15 +210,7 @@ function mergeYaml(target, source) {
|
|
|
302
210
|
}
|
|
303
211
|
}
|
|
304
212
|
);
|
|
305
|
-
|
|
306
|
-
fs.writeFileSync(
|
|
307
|
-
target,
|
|
308
|
-
yaml.dump(merged, {
|
|
309
|
-
styles: {
|
|
310
|
-
"!!null": "empty", // dump null as ""
|
|
311
|
-
},
|
|
312
|
-
})
|
|
313
|
-
);
|
|
213
|
+
dumpToYaml(merged, target);
|
|
314
214
|
}
|
|
315
215
|
|
|
316
216
|
function archiveFolder(appDir, format = "zip") {
|
|
@@ -393,6 +293,14 @@ function isDirSync(path) {
|
|
|
393
293
|
return stat.isDirectory();
|
|
394
294
|
}
|
|
395
295
|
|
|
296
|
+
function isDirExist(path) {
|
|
297
|
+
try {
|
|
298
|
+
return isDirSync(path);
|
|
299
|
+
} catch {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
396
304
|
function isFileExist(path) {
|
|
397
305
|
try {
|
|
398
306
|
fs.accessSync(
|
|
@@ -416,6 +324,18 @@ function parse2CorrectName(name) {
|
|
|
416
324
|
return name.replaceAll(" ", "-").toLowerCase();
|
|
417
325
|
}
|
|
418
326
|
|
|
327
|
+
async function sleep(ms) {
|
|
328
|
+
return new Promise((resolve) => {
|
|
329
|
+
setTimeout(resolve, ms);
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
async function md5String(str) {
|
|
334
|
+
const hash = createHash("md5");
|
|
335
|
+
hash.update(str);
|
|
336
|
+
return hash.digest("hex");
|
|
337
|
+
}
|
|
338
|
+
|
|
419
339
|
export {
|
|
420
340
|
ensureDir,
|
|
421
341
|
copyDotAppDir,
|
|
@@ -424,6 +344,7 @@ export {
|
|
|
424
344
|
findAppRootPath,
|
|
425
345
|
archiveFolder,
|
|
426
346
|
mergeYaml,
|
|
347
|
+
mergeYamlInMemory,
|
|
427
348
|
loadFromYaml,
|
|
428
349
|
dumpToYaml,
|
|
429
350
|
importDefault,
|
|
@@ -434,13 +355,14 @@ export {
|
|
|
434
355
|
toPair,
|
|
435
356
|
contextDirname,
|
|
436
357
|
isDirSync,
|
|
358
|
+
isDirExist,
|
|
437
359
|
GitIgnore,
|
|
438
360
|
isFileExist,
|
|
439
361
|
urlHostname,
|
|
440
|
-
|
|
441
|
-
findAppIsInstalled,
|
|
442
|
-
getInstalledApps,
|
|
443
|
-
checkSDKInstallStatus,
|
|
362
|
+
envTemplateFile,
|
|
444
363
|
createTemplateFile,
|
|
445
364
|
parse2CorrectName,
|
|
365
|
+
sleep,
|
|
366
|
+
md5String,
|
|
367
|
+
createTemplateFileCommon
|
|
446
368
|
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazycatcloud/lzc-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "lazycat cloud developer kit",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"test": "mocha"
|
|
7
|
-
"publish": "npm publish --access public"
|
|
6
|
+
"test": "mocha"
|
|
8
7
|
},
|
|
9
8
|
"mocha": {
|
|
10
9
|
"recursive": true,
|
|
@@ -48,6 +47,7 @@
|
|
|
48
47
|
"lodash.merge": "^4.6.2",
|
|
49
48
|
"lodash.mergewith": "^4.6.2",
|
|
50
49
|
"log-update": "^5.0.0",
|
|
50
|
+
"loglevel": "^1.8.0",
|
|
51
51
|
"minimist": "^1.2.5",
|
|
52
52
|
"node-fetch": "^2.6.6",
|
|
53
53
|
"node-stream-zip": "^1.15.0",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"semver": "^7.3.5",
|
|
56
56
|
"ssh2": "^1.5.0",
|
|
57
57
|
"ssh2-promise": "^1.0.2",
|
|
58
|
+
"tar": "^6.1.11",
|
|
58
59
|
"yargs": "^17.5.1"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
@@ -62,5 +63,9 @@
|
|
|
62
63
|
"chai": "^4.3.6",
|
|
63
64
|
"mocha": "^9.2.2",
|
|
64
65
|
"prettier": "^2.5.0"
|
|
66
|
+
},
|
|
67
|
+
"publishConfig": {
|
|
68
|
+
"registry": "https://registry.npmjs.org",
|
|
69
|
+
"access": "public"
|
|
65
70
|
}
|
|
66
71
|
}
|
package/scripts/cli.js
CHANGED
|
@@ -2,25 +2,82 @@
|
|
|
2
2
|
import process from "process";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import fs from "fs";
|
|
5
|
-
import
|
|
5
|
+
import logger from "loglevel";
|
|
6
6
|
import yargs from "yargs";
|
|
7
7
|
import { hideBin } from "yargs/helpers";
|
|
8
|
+
import chalk from "chalk";
|
|
8
9
|
|
|
10
|
+
import { contextDirname, importDefault } from "../lib/utils.js";
|
|
9
11
|
import Env from "../lib/env.js";
|
|
10
12
|
import { boxCommand } from "../lib/box/index.js";
|
|
13
|
+
import { lpkAppCommand, lpkProjectCommand } from "../lib/app/index.js";
|
|
11
14
|
const pkgInfo = JSON.parse(
|
|
12
15
|
fs.readFileSync(path.join(contextDirname(import.meta.url), "../package.json"))
|
|
13
16
|
);
|
|
14
17
|
|
|
18
|
+
// logger level middleware
|
|
19
|
+
const logLevelOriginalFactory = logger.methodFactory;
|
|
20
|
+
logger.methodFactory = function (methodName, logLevel, loggerName) {
|
|
21
|
+
let rawMethod = logLevelOriginalFactory(methodName, logLevel, loggerName);
|
|
22
|
+
return function (...args) {
|
|
23
|
+
let color = (msg) => chalk.gray;
|
|
24
|
+
switch (methodName) {
|
|
25
|
+
case "trace":
|
|
26
|
+
color = chalk.dim.cyan;
|
|
27
|
+
break;
|
|
28
|
+
case "debug":
|
|
29
|
+
color = chalk.blue;
|
|
30
|
+
break;
|
|
31
|
+
case "info":
|
|
32
|
+
color = chalk.green;
|
|
33
|
+
break;
|
|
34
|
+
case "warn":
|
|
35
|
+
color = chalk.magenta;
|
|
36
|
+
break;
|
|
37
|
+
case "error":
|
|
38
|
+
color = chalk.bold.red;
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
rawMethod(
|
|
42
|
+
`[${methodName}] ` +
|
|
43
|
+
args
|
|
44
|
+
.map((a) => {
|
|
45
|
+
let res = a;
|
|
46
|
+
if (typeof a == "object") {
|
|
47
|
+
res = JSON.stringify(a, undefined, 4);
|
|
48
|
+
}
|
|
49
|
+
return color(res);
|
|
50
|
+
})
|
|
51
|
+
.join(" ")
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
logger.setDefaultLevel("info");
|
|
56
|
+
function setLoggerLevel({ log }) {
|
|
57
|
+
logger.setLevel(log, false);
|
|
58
|
+
}
|
|
59
|
+
|
|
15
60
|
const program = yargs(hideBin(process.argv))
|
|
16
61
|
.scriptName("lzc-cli")
|
|
17
62
|
.usage("<command> [options]")
|
|
18
63
|
.version(`lzc-cli ${pkgInfo.version}`)
|
|
19
|
-
.
|
|
64
|
+
.option("log", {
|
|
65
|
+
type: "string",
|
|
66
|
+
default: "info",
|
|
67
|
+
describe: "log level 'trace', 'debug', 'info', 'warn', 'error'",
|
|
68
|
+
})
|
|
69
|
+
.option("help", {
|
|
70
|
+
alias: "h",
|
|
71
|
+
type: "boolean",
|
|
72
|
+
default: false,
|
|
73
|
+
})
|
|
74
|
+
.completion("completion", false);
|
|
20
75
|
|
|
76
|
+
// Set desc to false to create a hidden command. Hidden commands don’t show up
|
|
77
|
+
// in the help output and aren’t available for completion.
|
|
21
78
|
program.command({
|
|
22
79
|
command: "create <name>",
|
|
23
|
-
desc:
|
|
80
|
+
desc: false,
|
|
24
81
|
aliases: ["c"],
|
|
25
82
|
handler: async ({ name }) => {
|
|
26
83
|
let create = await importDefault("../cmds/create.js");
|
|
@@ -30,7 +87,7 @@ program.command({
|
|
|
30
87
|
|
|
31
88
|
program.command({
|
|
32
89
|
command: "init",
|
|
33
|
-
desc:
|
|
90
|
+
desc: false,
|
|
34
91
|
handler: async () => {
|
|
35
92
|
const { Init } = await import("../cmds/init.js");
|
|
36
93
|
new Init({ cwd: process.cwd() }).create();
|
|
@@ -39,7 +96,7 @@ program.command({
|
|
|
39
96
|
|
|
40
97
|
program.command({
|
|
41
98
|
command: "uninstall",
|
|
42
|
-
desc:
|
|
99
|
+
desc: false,
|
|
43
100
|
handler: async () => {
|
|
44
101
|
const { uninstall } = await importDefault("../cmds/app.js");
|
|
45
102
|
await uninstall();
|
|
@@ -48,7 +105,7 @@ program.command({
|
|
|
48
105
|
|
|
49
106
|
program.command({
|
|
50
107
|
command: "publish",
|
|
51
|
-
desc:
|
|
108
|
+
desc: false,
|
|
52
109
|
handler: async () => {
|
|
53
110
|
// 第一步 打包镜像
|
|
54
111
|
const Publisher = await importDefault("../cmds/publish.js");
|
|
@@ -64,7 +121,7 @@ program.command({
|
|
|
64
121
|
|
|
65
122
|
program.command({
|
|
66
123
|
command: "deploy",
|
|
67
|
-
desc:
|
|
124
|
+
desc: false,
|
|
68
125
|
handler: async () => {
|
|
69
126
|
const { deploy } = await importDefault("../cmds/app.js");
|
|
70
127
|
await deploy();
|
|
@@ -73,7 +130,7 @@ program.command({
|
|
|
73
130
|
|
|
74
131
|
program.command({
|
|
75
132
|
command: "build [context]",
|
|
76
|
-
desc:
|
|
133
|
+
desc: false,
|
|
77
134
|
builder: (args) => {
|
|
78
135
|
args.option("f", {
|
|
79
136
|
alias: "file",
|
|
@@ -116,7 +173,7 @@ let devSubCommands = [
|
|
|
116
173
|
];
|
|
117
174
|
program.command({
|
|
118
175
|
command: "dev",
|
|
119
|
-
desc:
|
|
176
|
+
desc: false,
|
|
120
177
|
builder: (args) => {
|
|
121
178
|
args.command(devSubCommands);
|
|
122
179
|
},
|
|
@@ -124,7 +181,7 @@ program.command({
|
|
|
124
181
|
|
|
125
182
|
program.command({
|
|
126
183
|
command: "log [project]",
|
|
127
|
-
desc:
|
|
184
|
+
desc: false,
|
|
128
185
|
builder: (args) => {
|
|
129
186
|
args.option("u", {
|
|
130
187
|
alias: "user",
|
|
@@ -141,7 +198,7 @@ program.command({
|
|
|
141
198
|
|
|
142
199
|
program.command({
|
|
143
200
|
command: "config [key] [value]",
|
|
144
|
-
desc:
|
|
201
|
+
desc: false,
|
|
145
202
|
builder: (args) => {
|
|
146
203
|
args.implies("key", "value");
|
|
147
204
|
args.option("g", {
|
|
@@ -158,5 +215,27 @@ program.command({
|
|
|
158
215
|
});
|
|
159
216
|
|
|
160
217
|
boxCommand(program);
|
|
218
|
+
lpkAppCommand(program);
|
|
219
|
+
lpkProjectCommand(program);
|
|
220
|
+
|
|
221
|
+
const parser = program
|
|
222
|
+
.strict()
|
|
223
|
+
.showHelpOnFail(false, "使用 lzc-cli help 查看更多帮助")
|
|
224
|
+
.middleware([setLoggerLevel])
|
|
225
|
+
.parse();
|
|
161
226
|
|
|
162
|
-
|
|
227
|
+
// 当没有参数的时候,默认显示帮助。
|
|
228
|
+
(async () => {
|
|
229
|
+
const argv = await parser;
|
|
230
|
+
if (argv._.length == 1) {
|
|
231
|
+
switch (argv._[0]) {
|
|
232
|
+
case "box":
|
|
233
|
+
case "app":
|
|
234
|
+
case "project":
|
|
235
|
+
program.showHelp();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
} else if (argv._.length == 0) {
|
|
239
|
+
program.showHelp();
|
|
240
|
+
}
|
|
241
|
+
})();
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
FROM
|
|
1
|
+
FROM registry.lazycat.cloud/lzc/lzcapp:0.1
|
|
2
2
|
|
|
3
3
|
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
COPY --from=golang:1.18-alpine /usr/local/go/ /usr/local/go/
|
|
6
|
+
|
|
7
|
+
RUN apk add --no-cache openssh rsync musl-dev curl openssl curl nodejs npm \
|
|
6
8
|
&& echo "root:root" | chpasswd
|
|
7
9
|
|
|
8
10
|
EXPOSE 22
|
|
@@ -13,4 +15,4 @@ COPY entrypoint.sh /entrypoint.sh
|
|
|
13
15
|
|
|
14
16
|
RUN chmod +x /entrypoint.sh
|
|
15
17
|
|
|
16
|
-
ENTRYPOINT
|
|
18
|
+
ENTRYPOINT ./entrypoint.sh
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
services:
|
|
2
2
|
${APP_ID}:
|
|
3
|
-
image: nginx:1.21.4-alpine
|
|
4
|
-
volumes:
|
|
5
|
-
- ./nginx.conf.template:/etc/nginx/templates/nginx.conf.template
|
|
6
|
-
- ./50x.html:/etc/nginx/50x.html
|
|
7
|
-
environment:
|
|
8
|
-
- NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx
|
|
9
|
-
- APP_DEBUG_PORT=${HTTP_SERVICE_PORT}
|
|
10
|
-
- APP_DEBUG_SHELL=debug-shell.${APP_ID}.lzcapp
|
|
11
|
-
command: [nginx, '-g', 'daemon off;']
|
|
12
|
-
depends_on:
|
|
13
|
-
- debug-shell
|
|
14
|
-
debug-shell:
|
|
15
3
|
image: ${APP_IMAGE_NAME}
|
|
16
4
|
pull_policy: build
|
|
17
5
|
build: .
|
|
6
|
+
environment:
|
|
7
|
+
- HTTP_SERVICE_PORT=${HTTP_SERVICE_PORT}
|
|
18
8
|
volumes:
|
|
19
9
|
- ./debug/ssh:/root/.ssh
|
|
20
10
|
- project-data:/root/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
FROM alpine
|
|
2
|
+
|
|
3
|
+
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
|
|
4
|
+
|
|
5
|
+
COPY --from=golang:1.18-alpine /usr/local/go/ /usr/local/go/
|
|
6
|
+
|
|
7
|
+
RUN apk add --no-cache openssh musl-dev curl openssl curl nodejs npm sshfs rsync \
|
|
8
|
+
&& echo "root:root" | chpasswd
|
|
9
|
+
|
|
10
|
+
EXPOSE 22
|
|
11
|
+
|
|
12
|
+
COPY sshd_config /etc/ssh/sshd_config
|
|
13
|
+
|
|
14
|
+
COPY entrypoint.sh /entrypoint.sh
|
|
15
|
+
|
|
16
|
+
RUN chmod +x /entrypoint.sh
|
|
17
|
+
|
|
18
|
+
CMD ["./entrypoint.sh"]
|