@lazycatcloud/lzc-cli 1.1.8 → 1.1.9
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/README.md +69 -11
- package/lib/api.js +71 -39
- package/lib/app/index.js +76 -21
- package/lib/app/lpk_build.js +95 -63
- package/lib/app/lpk_create.js +63 -41
- package/lib/app/lpk_create_generator.js +202 -0
- package/lib/app/lpk_devshell.js +393 -328
- package/lib/app/lpk_devshell_docker.js +211 -0
- package/lib/app/lpk_installer.js +63 -26
- package/lib/app/lpk_log.js +68 -0
- package/lib/app/lpk_status.js +18 -0
- package/lib/app/lpk_uninstall.js +19 -0
- package/lib/appstore/index.js +37 -0
- package/lib/appstore/login.js +96 -93
- package/lib/appstore/publish.js +62 -0
- package/lib/autologin.js +0 -78
- package/lib/box/api/clientapi.js +1322 -0
- package/lib/box/api/empty.js +35 -0
- package/lib/box/check_qemu.js +1 -0
- package/lib/box/index.js +41 -94
- package/lib/box/qemu_vm_mgr.js +208 -239
- package/lib/box/schemes/vm_box_system_debian.json +1 -1
- package/lib/docker-compose.js +1 -2
- package/lib/env.js +19 -101
- package/lib/key.js +1 -0
- package/lib/sdk.js +10 -25
- package/lib/utils.js +156 -132
- package/package.json +19 -10
- package/scripts/cli.js +14 -135
- package/template/_lpk/README.md +31 -0
- package/template/_lpk/exec.sh +19 -0
- package/template/_lpk/golang.manifest.yml.in +16 -0
- package/template/_lpk/lazycat.png +0 -0
- package/template/_lpk/lite.manifest.yml.in +19 -0
- package/template/_lpk/local_devshell/Dockerfile +16 -0
- package/template/_lpk/local_devshell/build.sh +5 -0
- package/template/_lpk/local_devshell/entrypoint.sh +87 -0
- package/template/{_lazycat/debug/shell → _lpk/local_devshell}/sshd_config +8 -8
- package/template/_lpk/manifest.yml.in +0 -1
- package/template/{vue/lzc-build.yml → _lpk/vue.lzc-build.yml.in} +9 -1
- package/template/golang/README.md +0 -2
- package/template/golang/_gitignore +2 -0
- package/template/golang/build.sh +6 -0
- package/template/golang/lazycat.png +0 -0
- package/template/golang/lzc-build.yml +9 -1
- package/template/golang/rego.go +15 -16
- package/template/golang/rego_test.go +13 -0
- package/template/ionic_vue3/lazycat.png +0 -0
- package/template/ionic_vue3/lzc-build.yml +9 -1
- package/template/lite/error_pages/502.html.tpl +13 -0
- package/template/lite/lazycat.png +0 -0
- package/template/lite/lzc-build.yml +60 -0
- package/cmds/app.js +0 -133
- package/cmds/config.js +0 -55
- package/cmds/create.js +0 -55
- package/cmds/dev.js +0 -130
- package/cmds/init.js +0 -125
- package/cmds/log.js +0 -103
- package/cmds/publish.js +0 -116
- package/lib/archiver.js +0 -105
- package/lib/box/hportal.js +0 -120
- package/lib/builder.js +0 -313
- package/lib/dev.js +0 -314
- package/lib/generator.js +0 -146
- package/template/_lazycat/_gitignore +0 -1
- package/template/_lazycat/app-config +0 -1
- package/template/_lazycat/debug/devforward/50x.html +0 -30
- package/template/_lazycat/debug/devforward/Dockerfile +0 -16
- package/template/_lazycat/debug/devforward/docker-compose.override.yml.in +0 -11
- package/template/_lazycat/debug/devforward/entrypoint.sh +0 -10
- package/template/_lazycat/debug/devforward/nginx.conf.template +0 -56
- package/template/_lazycat/debug/devforward/sshd_config +0 -116
- package/template/_lazycat/debug/shell/50x.html +0 -32
- package/template/_lazycat/debug/shell/Dockerfile +0 -18
- package/template/_lazycat/debug/shell/build.sh +0 -15
- package/template/_lazycat/debug/shell/docker-compose.override.yml.in +0 -13
- package/template/_lazycat/debug/shell/entrypoint.sh +0 -12
- package/template/_lazycat/docker-compose.yml.in +0 -15
- package/template/_lazycat/icon.svg +0 -1
- package/template/_lazycat/screenshot.png +0 -0
- package/template/_lpk/sync/Dockerfile +0 -16
- package/template/_lpk/sync/build.sh +0 -5
- package/template/_lpk/sync/entrypoint.sh +0 -8
- package/template/_lpk/sync/sshd_config +0 -117
- package/template/_lpk/sync.manifest.yml.in +0 -3
- package/template/release/golang/Dockerfile +0 -18
- package/template/release/golang/build.sh +0 -13
- package/template/release/ionic_vue3/Dockerfile +0 -10
- package/template/release/ionic_vue3/build.sh +0 -7
- package/template/release/ionic_vue3/docker-compose.yml.in +0 -3
- package/template/release/vue/Dockerfile +0 -10
- package/template/release/vue/build.sh +0 -10
- package/template/release/vue/docker-compose.yml.in +0 -3
- package/template/vue/README.md +0 -29
- package/template/vue/_dockerignore +0 -1
- package/template/vue/babel.config.js +0 -3
- package/template/vue/package.json +0 -43
- package/template/vue/public/favicon.ico +0 -0
- package/template/vue/public/index.html +0 -33
- package/template/vue/src/App.vue +0 -39
- package/template/vue/src/main.js +0 -8
- package/template/vue/src/todo.vue +0 -640
- package/template/vue/src/top-bar.vue +0 -100
- package/template/vue/src/webdav.vue +0 -183
- package/template/vue/vue.config.js +0 -21
package/lib/appstore/login.js
CHANGED
|
@@ -1,134 +1,137 @@
|
|
|
1
1
|
import fetch from "node-fetch";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import logger from "loglevel";
|
|
4
|
+
import env from "../env.js";
|
|
5
|
+
import inquirer from "inquirer";
|
|
3
6
|
import FormData from "form-data";
|
|
4
|
-
import process from "process";
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
import { APP_FOLDER, APP_CONFIG_FILE } from "../utils.js"
|
|
7
7
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
function genFormData(data) {
|
|
11
|
-
const form = new FormData();
|
|
12
|
-
for (const name in data) {
|
|
13
|
-
form.append(name, data[name]);
|
|
14
|
-
}
|
|
15
|
-
return form
|
|
16
|
-
}
|
|
8
|
+
const accountServerUrl = "https://account.lazycat.cloud";
|
|
17
9
|
|
|
18
10
|
function join(...params) {
|
|
19
11
|
var x = path.join(...params);
|
|
20
12
|
return x;
|
|
21
13
|
}
|
|
22
14
|
|
|
23
|
-
function
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
function login(username, password) {
|
|
16
|
+
const form = new FormData();
|
|
17
|
+
form.append("username", username);
|
|
18
|
+
form.append("password", password);
|
|
19
|
+
|
|
20
|
+
return fetch(join(accountServerUrl, "/api/login/signin"), {
|
|
26
21
|
method: "POST",
|
|
27
22
|
headers: {
|
|
28
|
-
"content-type": `multipart/form-data; boundary=${form.getBoundary()}
|
|
23
|
+
"content-type": `multipart/form-data; boundary=${form.getBoundary()}`,
|
|
29
24
|
},
|
|
30
|
-
body: form
|
|
31
|
-
}).then(async res => {
|
|
32
|
-
let bodyText = await res.text();
|
|
33
|
-
let body = JSON.parse(bodyText)
|
|
34
|
-
if (body.success) {
|
|
35
|
-
return Promise.resolve(body.data)
|
|
36
|
-
}
|
|
37
|
-
return Promise.reject(body.message)
|
|
38
|
-
}).then(data => {
|
|
39
|
-
setToken(username, password, data.token)
|
|
25
|
+
body: form,
|
|
40
26
|
})
|
|
27
|
+
.then(async (res) => {
|
|
28
|
+
let bodyText = await res.text();
|
|
29
|
+
let body = JSON.parse(bodyText);
|
|
30
|
+
if (body.success) {
|
|
31
|
+
return Promise.resolve(body.data);
|
|
32
|
+
}
|
|
33
|
+
return Promise.reject(body.message);
|
|
34
|
+
})
|
|
35
|
+
.then((data) => {
|
|
36
|
+
env.set({ token: data.token }, true);
|
|
37
|
+
logger.info("登录成功!");
|
|
38
|
+
});
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
async function
|
|
41
|
+
async function isLogin() {
|
|
44
42
|
try {
|
|
45
|
-
let token =
|
|
43
|
+
let token = env.get("token");
|
|
46
44
|
if (!token) {
|
|
47
|
-
return false
|
|
45
|
+
return false;
|
|
48
46
|
}
|
|
49
|
-
return fetch(join(
|
|
47
|
+
return fetch(join(accountServerUrl, "/api/user/current"), {
|
|
50
48
|
method: "GET",
|
|
51
49
|
headers: {
|
|
52
|
-
"X-User-Token": token
|
|
50
|
+
"X-User-Token": token,
|
|
53
51
|
},
|
|
54
|
-
}).then(async res => {
|
|
52
|
+
}).then(async (res) => {
|
|
55
53
|
let bodyText = await res.text();
|
|
56
|
-
let body = JSON.parse(bodyText)
|
|
54
|
+
let body = JSON.parse(bodyText);
|
|
57
55
|
if (body.success) {
|
|
58
|
-
return token
|
|
56
|
+
return token;
|
|
59
57
|
}
|
|
60
|
-
|
|
61
|
-
return false
|
|
62
|
-
})
|
|
58
|
+
logger.debug(body.message);
|
|
59
|
+
return false;
|
|
60
|
+
});
|
|
63
61
|
} catch (e) {
|
|
64
|
-
|
|
62
|
+
logger.trace(e);
|
|
63
|
+
return false;
|
|
65
64
|
}
|
|
66
|
-
|
|
67
|
-
return false
|
|
68
65
|
}
|
|
69
66
|
|
|
70
|
-
async function
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
async function askUserInfo() {
|
|
68
|
+
const noEmpty = (value) => value != "";
|
|
69
|
+
return await inquirer.prompt([
|
|
70
|
+
{
|
|
71
|
+
type: "input",
|
|
72
|
+
name: "username",
|
|
73
|
+
message: "请输入登录用户名",
|
|
74
|
+
validate: noEmpty,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: "password",
|
|
78
|
+
mask: "*",
|
|
79
|
+
name: "password",
|
|
80
|
+
message: "请输入登录密码",
|
|
81
|
+
validate: noEmpty,
|
|
82
|
+
},
|
|
83
|
+
]);
|
|
84
|
+
}
|
|
76
85
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
86
|
+
export async function reLogin() {
|
|
87
|
+
let token = await isLogin();
|
|
88
|
+
if (token) {
|
|
89
|
+
const questions = [
|
|
90
|
+
{
|
|
91
|
+
name: "relogin",
|
|
92
|
+
type: "input",
|
|
93
|
+
default: "n",
|
|
94
|
+
message: "检测到已经登录,是否重新登录(y/n):",
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
const answers = await inquirer.prompt(questions);
|
|
98
|
+
if (answers.relogin.toLowerCase() === "n") {
|
|
99
|
+
logger.info(`token: ${token}`);
|
|
100
|
+
return;
|
|
82
101
|
}
|
|
83
|
-
} catch (e) {
|
|
84
|
-
console.log(e);
|
|
85
102
|
}
|
|
86
|
-
removeToken()
|
|
87
|
-
throw "自动登录失败"
|
|
88
|
-
}
|
|
89
103
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
function setToken(username, password, token) {
|
|
93
|
-
let configHome = join(process.cwd(), APP_FOLDER, APP_CONFIG_FILE)
|
|
94
|
-
if (!fs.existsSync(configHome)) {
|
|
95
|
-
fs.mkdirSync(configHome, { recursive: true })
|
|
96
|
-
}
|
|
97
|
-
let tokenFile = join(configHome, TokenFile)
|
|
98
|
-
let content = JSON.stringify({ username, password, token })
|
|
99
|
-
fs.writeFileSync(tokenFile, content, {
|
|
100
|
-
encoding,
|
|
101
|
-
flag: "w",
|
|
102
|
-
mode: 0o666
|
|
103
|
-
})
|
|
104
|
+
let info = await askUserInfo();
|
|
105
|
+
await login(info.username, info.password);
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
function
|
|
107
|
-
let
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
throw "读取本地文件失败"
|
|
108
|
+
export async function autoLogin() {
|
|
109
|
+
let token = await isLogin();
|
|
110
|
+
if (token) {
|
|
111
|
+
logger.debug("appstore 已经登录");
|
|
112
|
+
return;
|
|
112
113
|
}
|
|
113
|
-
|
|
114
|
+
|
|
115
|
+
logger.debug("token错误,尝试自动登录");
|
|
116
|
+
let info = await askUserInfo();
|
|
117
|
+
await login(info.username, info.password);
|
|
114
118
|
}
|
|
115
119
|
|
|
116
|
-
function
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
export async function request(url, options = {}) {
|
|
121
|
+
await autoLogin();
|
|
122
|
+
|
|
123
|
+
const token = env.get("token");
|
|
124
|
+
|
|
125
|
+
let headers = {
|
|
126
|
+
"X-User-Token": token,
|
|
127
|
+
cookie: `userToken=${token}`,
|
|
128
|
+
};
|
|
129
|
+
if (options.headers) {
|
|
130
|
+
headers = Object.assign({}, options.headers, headers);
|
|
122
131
|
}
|
|
123
|
-
return obj
|
|
124
|
-
}
|
|
125
132
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return fs.rmSync(tokenFile)
|
|
129
|
-
}
|
|
133
|
+
options = Object.assign({}, options, { headers });
|
|
134
|
+
logger.trace(`fetch ${url}`, options);
|
|
130
135
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
AutoLogin
|
|
134
|
-
}
|
|
136
|
+
return fetch(url, options);
|
|
137
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { request } from "./login.js";
|
|
2
|
+
import logger from "loglevel";
|
|
3
|
+
import FormData from "form-data";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import inquirer from "inquirer";
|
|
6
|
+
import { spawnSync } from "node:child_process";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { isFileExist } from "../utils.js";
|
|
9
|
+
|
|
10
|
+
async function askChangeLog() {
|
|
11
|
+
const noEmpty = (value) => value != "";
|
|
12
|
+
return await inquirer.prompt([
|
|
13
|
+
{
|
|
14
|
+
name: "changelog",
|
|
15
|
+
type: "editor",
|
|
16
|
+
message: "填写 changelog 内容",
|
|
17
|
+
validate: noEmpty,
|
|
18
|
+
},
|
|
19
|
+
]);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class Publish {
|
|
23
|
+
constructor(baseUrl = "https://developer.lazycat.cloud/api/app") {
|
|
24
|
+
this.baseUrl = baseUrl;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async publish(pkgPath, changelog) {
|
|
28
|
+
const tempDir = fs.mkdtempSync(".lzc-cli-publish");
|
|
29
|
+
try {
|
|
30
|
+
spawnSync("unzip", ["-d", tempDir, pkgPath]);
|
|
31
|
+
if (isFileExist(path.join(tempDir, "devshell"))) {
|
|
32
|
+
throw "不能发布一个devshell的版本,请重新使用 `lzc-cli project build` 构建";
|
|
33
|
+
}
|
|
34
|
+
} finally {
|
|
35
|
+
fs.rmSync(tempDir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!changelog) {
|
|
39
|
+
const answer = await askChangeLog();
|
|
40
|
+
changelog = answer.changelog;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
logger.info("正在发布...");
|
|
44
|
+
const form = new FormData();
|
|
45
|
+
form.append("files", fs.createReadStream(pkgPath));
|
|
46
|
+
form.append("changelog", changelog);
|
|
47
|
+
|
|
48
|
+
return request(this.baseUrl + "/update", {
|
|
49
|
+
method: "POST",
|
|
50
|
+
body: form,
|
|
51
|
+
}).then(async (res) => {
|
|
52
|
+
if (res.status != 200) {
|
|
53
|
+
logger.error(await res.text());
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
logger.info("发布成功!");
|
|
58
|
+
logger.debug("publish response", await res.json());
|
|
59
|
+
return;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
package/lib/autologin.js
CHANGED
|
@@ -1,82 +1,4 @@
|
|
|
1
1
|
import fetch from "node-fetch";
|
|
2
|
-
|
|
3
|
-
// autologin.js 提供一个封装好的 fetch request 请求方法,通过这个中间件,可以不用考虑
|
|
4
|
-
// auth:auto 所做的授权验证。
|
|
5
|
-
let AutoLoginToken = "";
|
|
6
|
-
let AutoLoginFailed = false;
|
|
7
|
-
|
|
8
|
-
function fetchTokenAction(url) {
|
|
9
|
-
return fetch(url).then(async (res) => {
|
|
10
|
-
const body = await res.text();
|
|
11
|
-
const token = body.match(/name=\"token\" value=\"(.*?)\"/i)[1];
|
|
12
|
-
const action = body.match(/action=\"(.*?)\"/i)[1];
|
|
13
|
-
|
|
14
|
-
return { token, action };
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function fetchTokenActionAndRedirect(dataToken, dataAction) {
|
|
19
|
-
return fetch(dataAction, {
|
|
20
|
-
method: "POST",
|
|
21
|
-
body: `token=${dataToken}`,
|
|
22
|
-
redirect: "follow",
|
|
23
|
-
headers: {
|
|
24
|
-
accept:
|
|
25
|
-
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
|
26
|
-
"accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7",
|
|
27
|
-
"content-type": "application/x-www-form-urlencoded",
|
|
28
|
-
},
|
|
29
|
-
}).then(async (res) => {
|
|
30
|
-
let body = await res.text();
|
|
31
|
-
const token = body.match(/name=\"token\" value=\"(.*?)\"/i)[1];
|
|
32
|
-
const action = body.match(/action=\"(.*?)\"/i)[1];
|
|
33
|
-
const redirect = body.match(/name=\"redirect\" value=\"(.*?)\"/i)[1];
|
|
34
|
-
|
|
35
|
-
return { token, action, redirect };
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
2
|
export async function request(url, options = {}) {
|
|
40
|
-
if (AutoLoginFailed) {
|
|
41
|
-
return fetch(url, options);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
await tryAuthLogin(url);
|
|
45
|
-
|
|
46
|
-
if (!AutoLoginToken) {
|
|
47
|
-
return fetch(url, options);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
let headers = { cookie: `HC-Auth-Token=${AutoLoginToken}` };
|
|
51
|
-
if (options.headers) {
|
|
52
|
-
headers = Object.assign({}, options.headers, headers);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
options = Object.assign({}, options, { headers });
|
|
56
3
|
return fetch(url, options);
|
|
57
4
|
}
|
|
58
|
-
|
|
59
|
-
export async function tryAuthLogin(url) {
|
|
60
|
-
if (!url.startsWith("http")) {
|
|
61
|
-
url = "https://" + url;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
if (!AutoLoginToken) {
|
|
66
|
-
let _url = new URL(url);
|
|
67
|
-
let u = "sdk."+_url.host.split(".").reverse().slice(0, 3).reverse().join(".");
|
|
68
|
-
|
|
69
|
-
console.log(`登陆到 ${u}`);
|
|
70
|
-
|
|
71
|
-
let data = await fetchTokenAction(`${_url.protocol}//${u}`);
|
|
72
|
-
let data2 = await fetchTokenActionAndRedirect(data.token, data.action);
|
|
73
|
-
|
|
74
|
-
AutoLoginToken = data2.token;
|
|
75
|
-
return AutoLoginToken;
|
|
76
|
-
}
|
|
77
|
-
} catch (e) {
|
|
78
|
-
console.log(`无法登陆`);
|
|
79
|
-
AutoLoginFailed = true;
|
|
80
|
-
return "";
|
|
81
|
-
}
|
|
82
|
-
}
|