@lazycatcloud/lzc-cli 1.1.7 → 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/lib/api.js +4 -1
- package/lib/app/index.js +3 -2
- package/lib/app/lpk_build.js +17 -5
- package/lib/appstore/login.js +134 -0
- package/lib/autologin.js +3 -5
- package/lib/box/index.js +1 -1
- package/lib/env.js +7 -44
- package/lib/utils.js +0 -101
- package/package.json +2 -3
package/lib/api.js
CHANGED
|
@@ -28,8 +28,11 @@ export default class API {
|
|
|
28
28
|
// build boolean 是否构建app容器
|
|
29
29
|
// pull boolean 是否从docker.io拉取image
|
|
30
30
|
async install(zipPath, params) {
|
|
31
|
+
if (!fs.existsSync(zipPath)) {
|
|
32
|
+
throw `${zipPath} 不存在`
|
|
33
|
+
}
|
|
31
34
|
const resp = await request(
|
|
32
|
-
`${this.host}/api/v1/app/install`,
|
|
35
|
+
`${this.host}/api/v1/app/install?id=${this.appId}`,
|
|
33
36
|
{
|
|
34
37
|
method: "POST",
|
|
35
38
|
body: fs.createReadStream(zipPath),
|
package/lib/app/index.js
CHANGED
|
@@ -21,7 +21,7 @@ export function lpkProjectCommand(program) {
|
|
|
21
21
|
builder: (args) => {
|
|
22
22
|
args.option("o", {
|
|
23
23
|
alias: "output",
|
|
24
|
-
describe: "
|
|
24
|
+
describe: "输出文件",
|
|
25
25
|
type: "string",
|
|
26
26
|
});
|
|
27
27
|
},
|
|
@@ -31,8 +31,9 @@ export function lpkProjectCommand(program) {
|
|
|
31
31
|
// 正常的打包逻辑不需要 devshell
|
|
32
32
|
lpk.onBeforeBuildPackage(async (options) => {
|
|
33
33
|
delete options["devshell"];
|
|
34
|
+
|
|
34
35
|
if (output) {
|
|
35
|
-
options["
|
|
36
|
+
options["lpkPath"] = output;
|
|
36
37
|
}
|
|
37
38
|
return options;
|
|
38
39
|
});
|
package/lib/app/lpk_build.js
CHANGED
|
@@ -168,9 +168,13 @@ export class LpkBuild {
|
|
|
168
168
|
logger.warn("跳过执行 buildscript");
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
let packName = this.options["lpkPath"]
|
|
172
|
+
|
|
173
|
+
if (!packName) {
|
|
174
|
+
const pkgout = path.resolve(this.pwd, this.options["pkgout"]);
|
|
175
|
+
if (!isDirExist(pkgout)) {
|
|
176
|
+
throw `${pkgout} 不存在`;
|
|
177
|
+
}
|
|
174
178
|
}
|
|
175
179
|
|
|
176
180
|
const tempDir = fs.mkdtempSync(".lzc-cli-build");
|
|
@@ -202,6 +206,9 @@ export class LpkBuild {
|
|
|
202
206
|
|
|
203
207
|
// 开始生成 manifest.yml
|
|
204
208
|
let manifest = await this.getManifest();
|
|
209
|
+
if (process.env.LZC_VERSION) {
|
|
210
|
+
manifest.version = process.env.LZC_VERSION
|
|
211
|
+
}
|
|
205
212
|
if (this.beforeDumpYamlFn.length > 0) {
|
|
206
213
|
manifest = await this.beforeDumpYamlFn.reduce(async (prev, curr) => {
|
|
207
214
|
return await curr(await prev, this.options);
|
|
@@ -217,8 +224,13 @@ export class LpkBuild {
|
|
|
217
224
|
return prev;
|
|
218
225
|
}, {});
|
|
219
226
|
}
|
|
220
|
-
|
|
221
|
-
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
if (!packName) {
|
|
230
|
+
packName = `${prefix}${manifest.package}-v${manifest.version}.lpk`;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const lpkPath = await archiveFolderTo(tempDir, packName);
|
|
222
234
|
logger.info(`输出lpk包 ${lpkPath.path}`);
|
|
223
235
|
|
|
224
236
|
// remove temp file
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import fetch from "node-fetch";
|
|
2
|
+
import path from "path";
|
|
3
|
+
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
|
+
|
|
8
|
+
const server = "https://account.lazycat.cloud"
|
|
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
|
+
}
|
|
17
|
+
|
|
18
|
+
function join(...params) {
|
|
19
|
+
var x = path.join(...params);
|
|
20
|
+
return x;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function Login(username, password) {
|
|
24
|
+
let form = genFormData({ username, password })
|
|
25
|
+
return fetch(join(server, "/api/login/signin"), {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: {
|
|
28
|
+
"content-type": `multipart/form-data; boundary=${form.getBoundary()}`
|
|
29
|
+
},
|
|
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)
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function IsLogin() {
|
|
44
|
+
try {
|
|
45
|
+
let token = getToken()
|
|
46
|
+
if (!token) {
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
return fetch(join(server, "/api/user/current"), {
|
|
50
|
+
method: "GET",
|
|
51
|
+
headers: {
|
|
52
|
+
"X-User-Token": token
|
|
53
|
+
},
|
|
54
|
+
}).then(async res => {
|
|
55
|
+
let bodyText = await res.text();
|
|
56
|
+
let body = JSON.parse(bodyText)
|
|
57
|
+
if (body.success) {
|
|
58
|
+
return token
|
|
59
|
+
}
|
|
60
|
+
console.log(body.message);
|
|
61
|
+
return false
|
|
62
|
+
})
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.log(e);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return false
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function AutoLogin() {
|
|
71
|
+
try {
|
|
72
|
+
let token = await IsLogin()
|
|
73
|
+
if (!!token) {
|
|
74
|
+
return true
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log("token错误,尝试自动登录");
|
|
78
|
+
let obj = getLocalObj()
|
|
79
|
+
if (!!obj && !!obj.username && !!obj.password) {
|
|
80
|
+
let l = await Login(obj.username, obj.password)
|
|
81
|
+
return true
|
|
82
|
+
}
|
|
83
|
+
} catch (e) {
|
|
84
|
+
console.log(e);
|
|
85
|
+
}
|
|
86
|
+
removeToken()
|
|
87
|
+
throw "自动登录失败"
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const TokenFile = "user.json"
|
|
91
|
+
const encoding = "utf8"
|
|
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
|
+
}
|
|
105
|
+
|
|
106
|
+
function getToken() {
|
|
107
|
+
let tokenFile = join(process.cwd(), APP_FOLDER, APP_CONFIG_FILE, TokenFile)
|
|
108
|
+
let buf = fs.readFileSync(tokenFile, { encoding, flag: 'r' })
|
|
109
|
+
let obj = JSON.parse(buf)
|
|
110
|
+
if (!obj || !obj.token) {
|
|
111
|
+
throw "读取本地文件失败"
|
|
112
|
+
}
|
|
113
|
+
return obj.token
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function getLocalObj() {
|
|
117
|
+
let tokenFile = join(process.cwd(), APP_FOLDER, APP_CONFIG_FILE, TokenFile)
|
|
118
|
+
let buf = fs.readFileSync(tokenFile, { encoding, flag: 'r' })
|
|
119
|
+
let obj = JSON.parse(buf)
|
|
120
|
+
if (!obj || !obj.token) {
|
|
121
|
+
throw "读取本地文件失败"
|
|
122
|
+
}
|
|
123
|
+
return obj
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function removeToken() {
|
|
127
|
+
let tokenFile = join(process.cwd(), APP_FOLDER, APP_CONFIG_FILE, TokenFile)
|
|
128
|
+
return fs.rmSync(tokenFile)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export default {
|
|
132
|
+
Login,
|
|
133
|
+
AutoLogin
|
|
134
|
+
}
|
package/lib/autologin.js
CHANGED
|
@@ -64,20 +64,18 @@ export async function tryAuthLogin(url) {
|
|
|
64
64
|
try {
|
|
65
65
|
if (!AutoLoginToken) {
|
|
66
66
|
let _url = new URL(url);
|
|
67
|
-
let u = _url.host.split(".").reverse().slice(0, 3).reverse().join(".");
|
|
67
|
+
let u = "sdk."+_url.host.split(".").reverse().slice(0, 3).reverse().join(".");
|
|
68
68
|
|
|
69
|
-
console.log(
|
|
69
|
+
console.log(`登陆到 ${u}`);
|
|
70
70
|
|
|
71
71
|
let data = await fetchTokenAction(`${_url.protocol}//${u}`);
|
|
72
72
|
let data2 = await fetchTokenActionAndRedirect(data.token, data.action);
|
|
73
73
|
|
|
74
74
|
AutoLoginToken = data2.token;
|
|
75
|
-
console.log(`自动登录成功!`);
|
|
76
75
|
return AutoLoginToken;
|
|
77
76
|
}
|
|
78
77
|
} catch (e) {
|
|
79
|
-
console.
|
|
80
|
-
console.log(`尝试自动登录失败,正在使用默认的登录方式...`);
|
|
78
|
+
console.log(`无法登陆`);
|
|
81
79
|
AutoLoginFailed = true;
|
|
82
80
|
return "";
|
|
83
81
|
}
|
package/lib/box/index.js
CHANGED
|
@@ -71,7 +71,7 @@ export function boxCommand(box) {
|
|
|
71
71
|
if (!defaultBoxName) {
|
|
72
72
|
// 新创建的盒子在初始化的时候,盒子里面需要安装hc的组件,需要一点时间,
|
|
73
73
|
// 所以这里并不对sdk url进行校验是否有效
|
|
74
|
-
await sdkEnv.setDefaultBoxName(answer.boxName
|
|
74
|
+
await sdkEnv.setDefaultBoxName(answer.boxName);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
let h = await initHportal();
|
package/lib/env.js
CHANGED
|
@@ -5,9 +5,6 @@ import {
|
|
|
5
5
|
APP_CONFIG_FILE,
|
|
6
6
|
GLOBAL_CONFIG_DIR,
|
|
7
7
|
APP_FOLDER,
|
|
8
|
-
findAppIsInstalled,
|
|
9
|
-
checkSDKInstallStatus,
|
|
10
|
-
InstallSDK,
|
|
11
8
|
} from "./utils.js";
|
|
12
9
|
import { debuglog } from "util";
|
|
13
10
|
import inquirer from "inquirer";
|
|
@@ -251,29 +248,20 @@ class SDKEnv {
|
|
|
251
248
|
}
|
|
252
249
|
|
|
253
250
|
async ensure() {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
await this.installSDK(this.sdkUrl);
|
|
261
|
-
}
|
|
262
|
-
} else {
|
|
263
|
-
await this.setDefaultBoxName();
|
|
251
|
+
try {
|
|
252
|
+
const resp = await request(`${this.sdkUrl}/api/v1/ping`);
|
|
253
|
+
if (resp.status != 200) throw new Error(chalk.red("debug.bridge服务未正常运行"));
|
|
254
|
+
} catch (e) {
|
|
255
|
+
console.log(chalk.yellow("检测到SDK尚未安装,请将盒子开启开发者模式"));
|
|
256
|
+
process.exit(-1);
|
|
264
257
|
}
|
|
265
258
|
}
|
|
266
259
|
|
|
267
|
-
async setDefaultBoxName(boxname = ""
|
|
260
|
+
async setDefaultBoxName(boxname = "") {
|
|
268
261
|
if (!boxname) {
|
|
269
262
|
boxname = await this._promptAnswers();
|
|
270
263
|
}
|
|
271
264
|
let url = this.buildSdkUrl(boxname);
|
|
272
|
-
|
|
273
|
-
if (ensureSDK) {
|
|
274
|
-
await this.installSDK(url);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
265
|
env.set({ DEFAULT_BOXNAME: boxname }, true);
|
|
278
266
|
}
|
|
279
267
|
|
|
@@ -285,31 +273,6 @@ class SDKEnv {
|
|
|
285
273
|
return await checkURL(host, "/api/v1/ping");
|
|
286
274
|
}
|
|
287
275
|
|
|
288
|
-
/**
|
|
289
|
-
* 确保sdk已安装
|
|
290
|
-
* @param need_answer {boolean} 是否需要询问用户地址
|
|
291
|
-
*/
|
|
292
|
-
async installSDK(sdkURL) {
|
|
293
|
-
// 无法直接从环境变量拿到SDK_URL,就让用户输入
|
|
294
|
-
debug(sdkURL);
|
|
295
|
-
|
|
296
|
-
let boxURL = sdkURL.replace("sdk.", "");
|
|
297
|
-
|
|
298
|
-
try {
|
|
299
|
-
if (await findAppIsInstalled(boxURL, "sdk")) {
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
console.log(chalk.yellow("检测到SDK尚未安装,开始安装SDK"));
|
|
304
|
-
await InstallSDK(boxURL);
|
|
305
|
-
console.log(chalk.green("SDK安装完成,开始部署SDK"));
|
|
306
|
-
|
|
307
|
-
await checkSDKInstallStatus(boxURL);
|
|
308
|
-
} catch (e) {
|
|
309
|
-
throw e;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
276
|
/**
|
|
314
277
|
* 提示用户回答问题
|
|
315
278
|
*
|
package/lib/utils.js
CHANGED
|
@@ -27,103 +27,6 @@ export const envsubstr = async (templateContents, args) => {
|
|
|
27
27
|
const parse = await importDefault("envsub/js/envsub-parser.js");
|
|
28
28
|
return parse(templateContents, args);
|
|
29
29
|
};
|
|
30
|
-
/**
|
|
31
|
-
* 为盒子安装SDK应用
|
|
32
|
-
* @param box_url 盒子入口地址
|
|
33
|
-
**/
|
|
34
|
-
async function InstallSDK(box_url) {
|
|
35
|
-
try {
|
|
36
|
-
let url = `${box_url}/api/app/apply?id=sdk`;
|
|
37
|
-
const resp = await request(url, { method: "post" });
|
|
38
|
-
if (resp.status != 200) {
|
|
39
|
-
throw new Error(
|
|
40
|
-
chalk.red(
|
|
41
|
-
`无法安装, 请确保 ${chalk.yellow(
|
|
42
|
-
new URL(url).origin
|
|
43
|
-
)} 可以访问或者在应用商店安装 sdk`
|
|
44
|
-
)
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
} catch (err) {
|
|
48
|
-
throw err;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* 检查SDK安装部署的状态
|
|
53
|
-
* @param box_url 盒子入口地址
|
|
54
|
-
**/
|
|
55
|
-
async function checkSDKInstallStatus(box_url) {
|
|
56
|
-
const checkSDKstatus = async function (box_url) {
|
|
57
|
-
let url = `${box_url}/api/app/status?id=sdk`;
|
|
58
|
-
const resp = await request(url);
|
|
59
|
-
if (resp.status == 200) {
|
|
60
|
-
const status = await resp.json();
|
|
61
|
-
return status;
|
|
62
|
-
} else {
|
|
63
|
-
let text = await resp.text();
|
|
64
|
-
throw text;
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
const spinner = ora().start();
|
|
68
|
-
let { status, info } = await checkSDKstatus(box_url);
|
|
69
|
-
spinner.text = "部署进度";
|
|
70
|
-
switch (status) {
|
|
71
|
-
case "running":
|
|
72
|
-
console.log(chalk.yellow("应用正在运行中"));
|
|
73
|
-
break;
|
|
74
|
-
case "error":
|
|
75
|
-
spinner.stop();
|
|
76
|
-
console.log(status, info);
|
|
77
|
-
throw info.msg;
|
|
78
|
-
default:
|
|
79
|
-
try {
|
|
80
|
-
await desireStatusTimer(
|
|
81
|
-
(result) => {
|
|
82
|
-
spinner.text = "部署进度 " + result.status;
|
|
83
|
-
return result.status === "running";
|
|
84
|
-
},
|
|
85
|
-
() => {
|
|
86
|
-
return checkSDKstatus(box_url);
|
|
87
|
-
}
|
|
88
|
-
);
|
|
89
|
-
} catch (error) {
|
|
90
|
-
throw error;
|
|
91
|
-
} finally {
|
|
92
|
-
spinner.stop();
|
|
93
|
-
}
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
spinner.stop();
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* 获取所有已安装的app
|
|
101
|
-
* @param box_url 盒子入口地址
|
|
102
|
-
**/
|
|
103
|
-
async function getInstalledApps(box_url) {
|
|
104
|
-
try {
|
|
105
|
-
let url = `${box_url}/api/app/dump`;
|
|
106
|
-
const resp = await request(url);
|
|
107
|
-
if (resp.status != 200) throw new Error(chalk.red("获取所有已安装App失败"));
|
|
108
|
-
return await resp.json();
|
|
109
|
-
} catch (e) {
|
|
110
|
-
console.log(e);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* 查找某个app是否已安装]
|
|
115
|
-
* @param box_url 盒子入口地址
|
|
116
|
-
* @param app_id app名
|
|
117
|
-
* */
|
|
118
|
-
async function findAppIsInstalled(box_url, app_id) {
|
|
119
|
-
const apps = await getInstalledApps(box_url);
|
|
120
|
-
for (let app in apps) {
|
|
121
|
-
if (app == app_id) {
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
30
|
|
|
128
31
|
/**
|
|
129
32
|
* 确保文件夹存在
|
|
@@ -456,10 +359,6 @@ export {
|
|
|
456
359
|
GitIgnore,
|
|
457
360
|
isFileExist,
|
|
458
361
|
urlHostname,
|
|
459
|
-
InstallSDK,
|
|
460
|
-
findAppIsInstalled,
|
|
461
|
-
getInstalledApps,
|
|
462
|
-
checkSDKInstallStatus,
|
|
463
362
|
envTemplateFile,
|
|
464
363
|
createTemplateFile,
|
|
465
364
|
parse2CorrectName,
|
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,
|