@lazycatcloud/lzc-cli 1.1.0 → 1.1.3
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 +34 -36
- package/lib/archiver.js +50 -31
- package/lib/box/hportal.js +113 -0
- package/lib/box/index.js +135 -0
- package/lib/box/qemu_vm_mgr.js +553 -0
- package/lib/box/schemes/vm_box_system_debian.json +47 -0
- package/lib/builder.js +154 -35
- package/lib/dev.js +39 -31
- package/lib/env.js +276 -58
- package/lib/generator.js +31 -0
- package/lib/git/git-commit.sh +7 -0
- package/lib/git/git-reset.sh +15 -0
- package/lib/key.js +14 -25
- package/lib/sdk.js +7 -10
- package/lib/utils.js +149 -52
- package/package.json +14 -2
- package/scripts/auto-completion.sh +46 -0
- package/scripts/cli.js +134 -70
- package/template/_lazycat/app-config +1 -0
- package/template/_lazycat/docker-compose.yml.in +3 -5
- package/template/golang/README.md +3 -4
- package/template/golang/assets/css/bootstrap-responsive.css +26 -23
- package/template/golang/assets/css/bootstrap-responsive.min.css +1065 -1
- package/template/golang/assets/css/bootstrap.css +733 -362
- package/template/golang/assets/css/bootstrap.min.css +5299 -1
- package/template/golang/assets/css/rego.css +17 -17
- package/template/golang/assets/js/bootstrap.js +1340 -1311
- package/template/golang/assets/js/bootstrap.min.js +1240 -5
- package/template/golang/assets/js/rego.js +80 -69
- package/template/golang/index.html +61 -59
- package/template/ionic_vue3/README.md +46 -0
- package/template/ionic_vue3/_eslintrc.cjs +24 -0
- package/template/ionic_vue3/_gitignore +29 -0
- package/template/ionic_vue3/_vscode/extensions.json +6 -0
- package/template/ionic_vue3/capacitor.config.ts +10 -0
- package/template/ionic_vue3/env.d.ts +1 -0
- package/template/ionic_vue3/index.html +13 -0
- package/template/ionic_vue3/ionic.config.json +7 -0
- package/template/ionic_vue3/package.json +52 -0
- package/template/ionic_vue3/postcss.config.js +6 -0
- package/template/ionic_vue3/public/favicon.ico +0 -0
- package/template/ionic_vue3/src/App.vue +11 -0
- package/template/ionic_vue3/src/assets/logo.svg +1 -0
- package/template/ionic_vue3/src/index.css +3 -0
- package/template/ionic_vue3/src/main.ts +35 -0
- package/template/ionic_vue3/src/router/index.ts +15 -0
- package/template/ionic_vue3/src/theme/variables.css +231 -0
- package/template/ionic_vue3/src/views/Home.vue +38 -0
- package/template/ionic_vue3/tailwind.config.js +7 -0
- package/template/ionic_vue3/tsconfig.json +16 -0
- package/template/ionic_vue3/tsconfig.vite-config.json +8 -0
- package/template/ionic_vue3/vite.config.ts +28 -0
- package/template/release/golang/build.sh +1 -2
- package/template/release/ionic_vue3/Dockerfile +10 -0
- package/template/release/ionic_vue3/build.sh +9 -0
- package/template/release/ionic_vue3/docker-compose.yml.in +8 -0
- package/template/release/vue/Dockerfile +3 -2
- package/template/release/vue/build.sh +4 -2
- package/template/vue/README.md +5 -0
- package/template/vue/babel.config.js +2 -4
package/lib/utils.js
CHANGED
|
@@ -5,7 +5,6 @@ import os from "os";
|
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import archiver from "archiver";
|
|
7
7
|
import glob from "fast-glob";
|
|
8
|
-
import envsub from "envsub";
|
|
9
8
|
import yaml from "js-yaml";
|
|
10
9
|
import mergeWith from "lodash.mergewith";
|
|
11
10
|
import isArray from "lodash.isarray";
|
|
@@ -13,43 +12,130 @@ import fetch from "node-fetch";
|
|
|
13
12
|
import { dirname } from "path";
|
|
14
13
|
import { fileURLToPath } from "url";
|
|
15
14
|
import ignore from "ignore";
|
|
15
|
+
import ora from "ora";
|
|
16
|
+
import { desireStatusTimer } from "../lib/api.js";
|
|
17
|
+
import { warn } from "console";
|
|
16
18
|
|
|
17
|
-
const controller = new AbortController();
|
|
18
19
|
const META_MARK = "x-lazycat-app";
|
|
19
20
|
const APP_FOLDER = ".lazycat";
|
|
20
21
|
const APP_CONFIG_FILE = "app-config";
|
|
21
22
|
const APP_SDK_HOSTNAME = "box";
|
|
23
|
+
export const GLOBAL_CONFIG_DIR = path.join(os.homedir(), "/.config/lazycat");
|
|
22
24
|
|
|
23
25
|
export const envsubstr = async (templateContents, args) => {
|
|
24
26
|
const parse = await importDefault("envsub/js/envsub-parser.js");
|
|
25
27
|
return parse(templateContents, args);
|
|
26
28
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
controller.abort();
|
|
33
|
-
}, 5000);
|
|
34
|
-
|
|
29
|
+
/**
|
|
30
|
+
* 为盒子安装SDK应用
|
|
31
|
+
* @param box_url 盒子入口地址
|
|
32
|
+
**/
|
|
33
|
+
async function InstallSDK(box_url) {
|
|
35
34
|
try {
|
|
36
|
-
|
|
35
|
+
let url = `${box_url}/api/app/apply?id=sdk`;
|
|
36
|
+
const resp = await fetch(url, { method: "post" });
|
|
37
37
|
if (resp.status != 200) {
|
|
38
|
-
throw new Error(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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;
|
|
43
122
|
}
|
|
44
|
-
} catch (error) {
|
|
45
|
-
throw error;
|
|
46
|
-
} finally {
|
|
47
|
-
clearTimeout(timeout);
|
|
48
123
|
}
|
|
124
|
+
return false;
|
|
49
125
|
}
|
|
50
126
|
|
|
127
|
+
/**
|
|
128
|
+
* 确保文件夹存在
|
|
129
|
+
* @param filePath {string} 如果为文件路径 确保其文件夹存在; 如果为文件夹, 则确保该文件夹存在
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
51
132
|
function ensureDir(filePath) {
|
|
52
|
-
|
|
133
|
+
let dirPath;
|
|
134
|
+
if (filePath.endsWith("/")) {
|
|
135
|
+
dirPath = filePath;
|
|
136
|
+
} else {
|
|
137
|
+
dirPath = path.dirname(filePath);
|
|
138
|
+
}
|
|
53
139
|
if (!fs.existsSync(dirPath)) {
|
|
54
140
|
fs.mkdirSync(dirPath, { recursive: true });
|
|
55
141
|
}
|
|
@@ -117,7 +203,7 @@ function getMetaInfo(composeFile) {
|
|
|
117
203
|
return doc[META_MARK];
|
|
118
204
|
}
|
|
119
205
|
|
|
120
|
-
async function
|
|
206
|
+
async function createTemplateFile(templateFile, outputFile, env) {
|
|
121
207
|
const template = yaml.load(fs.readFileSync(templateFile, "utf8"));
|
|
122
208
|
// const meta = template[META_MARK];
|
|
123
209
|
// if (
|
|
@@ -134,7 +220,7 @@ async function convertTemplateFile(templateFile, outputFile, env) {
|
|
|
134
220
|
// authcallback: "/lzcapis/oidc-callback",
|
|
135
221
|
// });
|
|
136
222
|
// template["services"]["lazycat-apis-sidecar"] = {
|
|
137
|
-
// image: "registry.
|
|
223
|
+
// image: "registry.lazycat.cloud/lazycat-apis-sidecar",
|
|
138
224
|
// // volumes_from: ["${APP_NAME}:rw"],
|
|
139
225
|
// volumes: ["lzcapis-lzcapp:/lzcapp"],
|
|
140
226
|
// command: [
|
|
@@ -191,7 +277,7 @@ async function copyDotAppDir(from, to, opts = {}) {
|
|
|
191
277
|
}
|
|
192
278
|
ensureDir(outputFile);
|
|
193
279
|
if (needConvert) {
|
|
194
|
-
await
|
|
280
|
+
await createTemplateFile(templateFile, outputFile, env);
|
|
195
281
|
} else {
|
|
196
282
|
fs.copyFileSync(templateFile, outputFile);
|
|
197
283
|
}
|
|
@@ -255,8 +341,8 @@ function archiveFolder(appDir, format = "zip") {
|
|
|
255
341
|
});
|
|
256
342
|
}
|
|
257
343
|
|
|
258
|
-
function contextDirname() {
|
|
259
|
-
return dirname(fileURLToPath(
|
|
344
|
+
function contextDirname(url = import.meta.url) {
|
|
345
|
+
return dirname(fileURLToPath(url));
|
|
260
346
|
}
|
|
261
347
|
|
|
262
348
|
async function importDefault(pkgPath) {
|
|
@@ -265,39 +351,39 @@ async function importDefault(pkgPath) {
|
|
|
265
351
|
}
|
|
266
352
|
|
|
267
353
|
class GitIgnore {
|
|
268
|
-
constructor() {
|
|
269
|
-
this.
|
|
354
|
+
constructor(root) {
|
|
355
|
+
this.root = root;
|
|
356
|
+
this.ignores = [];
|
|
270
357
|
}
|
|
271
358
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
// if not exist .gitignore
|
|
279
|
-
}
|
|
280
|
-
}
|
|
359
|
+
async collect() {
|
|
360
|
+
const files = await glob(["**/.gitignore"], {
|
|
361
|
+
cwd: this.root,
|
|
362
|
+
dot: true,
|
|
363
|
+
deep: 3,
|
|
364
|
+
});
|
|
281
365
|
|
|
282
|
-
|
|
283
|
-
return this.ig.ignores(filepath);
|
|
366
|
+
files.forEach((f) => this._add(f));
|
|
284
367
|
}
|
|
285
368
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
369
|
+
_add(ignoreFile) {
|
|
370
|
+
let data = fs.readFileSync(ignoreFile, "utf8");
|
|
371
|
+
let ig = ignore({ allowRelativePaths: true });
|
|
372
|
+
ig.add(data.split("\n"));
|
|
373
|
+
this.ignores.push({
|
|
374
|
+
ig,
|
|
375
|
+
dir: path.dirname(ignoreFile),
|
|
376
|
+
});
|
|
377
|
+
}
|
|
293
378
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
379
|
+
contain(filepath) {
|
|
380
|
+
return this.ignores.some(({ ig, dir }) => {
|
|
381
|
+
// 去除不应该计算ignore 的文件
|
|
382
|
+
if (!filepath.startsWith(dir)) {
|
|
383
|
+
return false;
|
|
297
384
|
}
|
|
298
385
|
|
|
299
|
-
|
|
300
|
-
return callback(err, validFiles);
|
|
386
|
+
return ig.ignores(path.relative(dir, filepath));
|
|
301
387
|
});
|
|
302
388
|
}
|
|
303
389
|
}
|
|
@@ -324,6 +410,12 @@ function urlHostname(url) {
|
|
|
324
410
|
return u.hostname;
|
|
325
411
|
}
|
|
326
412
|
|
|
413
|
+
// REVIEW: 用户输入的app-id 空格替换为减号并且转换为全小写。
|
|
414
|
+
// 这会影响默认的app-name,因为app-name的默认值依赖app-id,但是如果特定输入了app-name则正常
|
|
415
|
+
function parse2CorrectName(name) {
|
|
416
|
+
return name.replaceAll(" ", "-").toLowerCase();
|
|
417
|
+
}
|
|
418
|
+
|
|
327
419
|
export {
|
|
328
420
|
ensureDir,
|
|
329
421
|
copyDotAppDir,
|
|
@@ -332,7 +424,6 @@ export {
|
|
|
332
424
|
findAppRootPath,
|
|
333
425
|
archiveFolder,
|
|
334
426
|
mergeYaml,
|
|
335
|
-
checkURL,
|
|
336
427
|
loadFromYaml,
|
|
337
428
|
dumpToYaml,
|
|
338
429
|
importDefault,
|
|
@@ -346,4 +437,10 @@ export {
|
|
|
346
437
|
GitIgnore,
|
|
347
438
|
isFileExist,
|
|
348
439
|
urlHostname,
|
|
440
|
+
InstallSDK,
|
|
441
|
+
findAppIsInstalled,
|
|
442
|
+
getInstalledApps,
|
|
443
|
+
checkSDKInstallStatus,
|
|
444
|
+
createTemplateFile,
|
|
445
|
+
parse2CorrectName,
|
|
349
446
|
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazycatcloud/lzc-cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "lazycat cloud developer kit",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"test": "
|
|
6
|
+
"test": "mocha",
|
|
7
|
+
"publish": "npm publish --access public"
|
|
8
|
+
},
|
|
9
|
+
"mocha": {
|
|
10
|
+
"recursive": true,
|
|
11
|
+
"reporter": "spec",
|
|
12
|
+
"timeout": 5000
|
|
7
13
|
},
|
|
8
14
|
"files": [
|
|
9
15
|
"template",
|
|
@@ -23,7 +29,9 @@
|
|
|
23
29
|
"@balena/dockerignore": "^1.0.2",
|
|
24
30
|
"archiver": "^5.3.0",
|
|
25
31
|
"chalk": "^4.1.2",
|
|
32
|
+
"chokidar": "^3.5.3",
|
|
26
33
|
"commander": "^8.3.0",
|
|
34
|
+
"commander-completion": "^1.0.1",
|
|
27
35
|
"dockerfile-ast": "^0.4.1",
|
|
28
36
|
"dockerode": "^3.3.1",
|
|
29
37
|
"ejs": "^3.1.6",
|
|
@@ -40,14 +48,18 @@
|
|
|
40
48
|
"lodash.merge": "^4.6.2",
|
|
41
49
|
"lodash.mergewith": "^4.6.2",
|
|
42
50
|
"log-update": "^5.0.0",
|
|
51
|
+
"lz4": "^0.6.5",
|
|
43
52
|
"minimist": "^1.2.5",
|
|
44
53
|
"node-fetch": "^2.6.6",
|
|
54
|
+
"node-stream-zip": "^1.15.0",
|
|
45
55
|
"ora": "^6.0.1",
|
|
46
56
|
"semver": "^7.3.5",
|
|
47
57
|
"ssh2": "^1.5.0",
|
|
48
58
|
"ssh2-promise": "^1.0.2"
|
|
49
59
|
},
|
|
50
60
|
"devDependencies": {
|
|
61
|
+
"chai": "^4.3.6",
|
|
62
|
+
"mocha": "^9.2.2",
|
|
51
63
|
"prettier": "^2.5.0"
|
|
52
64
|
}
|
|
53
65
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Forked from https://github.com/isaacs/npm/blob/v1.3.17/lib/utils/completion.sh
|
|
2
|
+
# Forked from https://github.com/twolfson/foundry/blob/4.3.3/bin/completion/foundry
|
|
3
|
+
#!/bin/bash
|
|
4
|
+
###-begin-lzc-cli-completion-###
|
|
5
|
+
#
|
|
6
|
+
# foundry command completion script
|
|
7
|
+
#
|
|
8
|
+
# Installation: lzc-cli completion >> ~/.bashrc (or ~/.zshrc)
|
|
9
|
+
# Or, maybe: lzc-cli completion > /usr/local/etc/bash_completion.d/lzc-cli
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
COMP_WORDBREAKS=${COMP_WORDBREAKS/=/}
|
|
13
|
+
COMP_WORDBREAKS=${COMP_WORDBREAKS/@/}
|
|
14
|
+
export COMP_WORDBREAKS
|
|
15
|
+
|
|
16
|
+
if type complete &>/dev/null; then
|
|
17
|
+
_lzc_cli_completion () {
|
|
18
|
+
local si="$IFS"
|
|
19
|
+
IFS=$'\n' COMPREPLY=($(COMP_CWORD="$COMP_CWORD" \
|
|
20
|
+
COMP_LINE="$COMP_LINE" \
|
|
21
|
+
COMP_POINT="$COMP_POINT" \
|
|
22
|
+
lzc-cli completion -- "${COMP_WORDS[@]}" \
|
|
23
|
+
2>/dev/null)) || return $?
|
|
24
|
+
IFS="$si"
|
|
25
|
+
}
|
|
26
|
+
complete -F _lzc_cli_completion lzc-cli
|
|
27
|
+
# DEV: We removed `compdef` due to issues with `zsh` (zsh 5.0.0 (x86_64-unknown-linux-gnu))
|
|
28
|
+
elif type compctl &>/dev/null; then
|
|
29
|
+
_lzc_cli_completion () {
|
|
30
|
+
local cword line point words si
|
|
31
|
+
read -Ac words
|
|
32
|
+
read -cn cword
|
|
33
|
+
let cword-=1
|
|
34
|
+
read -l line
|
|
35
|
+
read -ln point
|
|
36
|
+
si="$IFS"
|
|
37
|
+
IFS=$'\n' reply=($(COMP_CWORD="$cword" \
|
|
38
|
+
COMP_LINE="$line" \
|
|
39
|
+
COMP_POINT="$point" \
|
|
40
|
+
lzc-cli completion -- "${words[@]}" \
|
|
41
|
+
2>/dev/null)) || return $?
|
|
42
|
+
IFS="$si"
|
|
43
|
+
}
|
|
44
|
+
compctl -K _lzc_cli_completion lzc-cli
|
|
45
|
+
fi
|
|
46
|
+
###-end-lzc-cli-completion-###
|
package/scripts/cli.js
CHANGED
|
@@ -1,98 +1,162 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import program from "commander";
|
|
4
2
|
import process from "process";
|
|
5
3
|
import path from "path";
|
|
6
4
|
import fs from "fs";
|
|
7
5
|
import { contextDirname, importDefault } from "../lib/utils.js";
|
|
8
|
-
import
|
|
6
|
+
import yargs from "yargs";
|
|
7
|
+
import { hideBin } from "yargs/helpers";
|
|
9
8
|
|
|
9
|
+
import Env from "../lib/env.js";
|
|
10
|
+
import { boxCommand } from "../lib/box/index.js";
|
|
10
11
|
const pkgInfo = JSON.parse(
|
|
11
|
-
fs.readFileSync(path.join(contextDirname(), "../package.json"))
|
|
12
|
+
fs.readFileSync(path.join(contextDirname(import.meta.url), "../package.json"))
|
|
12
13
|
);
|
|
13
14
|
|
|
14
|
-
program.
|
|
15
|
-
|
|
16
|
-
program
|
|
17
|
-
.version(`lzc-cli ${pkgInfo.version}`)
|
|
15
|
+
const program = yargs(hideBin(process.argv))
|
|
16
|
+
.scriptName("lzc-cli")
|
|
18
17
|
.usage("<command> [options]")
|
|
19
|
-
.
|
|
20
|
-
.
|
|
21
|
-
|
|
18
|
+
.version(`lzc-cli ${pkgInfo.version}`)
|
|
19
|
+
.completion("completion", "生成bash/zsh补全脚本");
|
|
20
|
+
|
|
21
|
+
program.command({
|
|
22
|
+
command: "create <name>",
|
|
23
|
+
desc: "创建懒猫云应用",
|
|
24
|
+
aliases: ["c"],
|
|
25
|
+
handler: async ({ name }) => {
|
|
22
26
|
let create = await importDefault("../cmds/create.js");
|
|
23
27
|
await create({ name });
|
|
24
|
-
}
|
|
28
|
+
},
|
|
29
|
+
});
|
|
25
30
|
|
|
26
|
-
program
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
program.command({
|
|
32
|
+
command: "init",
|
|
33
|
+
desc: "初始化懒猫云应用配置",
|
|
34
|
+
handler: async () => {
|
|
30
35
|
const { Init } = await import("../cmds/init.js");
|
|
31
36
|
new Init({ cwd: process.cwd() }).create();
|
|
32
|
-
}
|
|
37
|
+
},
|
|
38
|
+
});
|
|
33
39
|
|
|
34
|
-
program
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
program.command({
|
|
41
|
+
command: "uninstall",
|
|
42
|
+
desc: "卸载应用",
|
|
43
|
+
handler: async () => {
|
|
38
44
|
const { uninstall } = await importDefault("../cmds/app.js");
|
|
39
45
|
await uninstall();
|
|
40
|
-
}
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
program.command({
|
|
50
|
+
command: "publish",
|
|
51
|
+
desc: "发布应用",
|
|
52
|
+
handler: async () => {
|
|
53
|
+
// 第一步 打包镜像
|
|
54
|
+
const Publisher = await importDefault("../cmds/publish.js");
|
|
55
|
+
const publisher = new Publisher();
|
|
56
|
+
await publisher.run();
|
|
57
|
+
// const b = builder();
|
|
58
|
+
// const contextDir = process.cwd()
|
|
59
|
+
// const dockerfile = Env.get("BUILD_CONTEXT")
|
|
60
|
+
// b.dockerRemoteBuildV2()
|
|
61
|
+
// 第二步
|
|
62
|
+
},
|
|
63
|
+
});
|
|
41
64
|
|
|
42
|
-
program
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
65
|
+
program.command({
|
|
66
|
+
command: "deploy",
|
|
67
|
+
desc: "部署应用至设备",
|
|
68
|
+
handler: async () => {
|
|
46
69
|
const { deploy } = await importDefault("../cmds/app.js");
|
|
47
70
|
await deploy();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
program
|
|
51
|
-
.command("build")
|
|
52
|
-
.argument("[context]", "integer argument")
|
|
53
|
-
.option("-f, --file <file>", "", "Dockerfile")
|
|
54
|
-
.action(async (context, options) => {
|
|
55
|
-
const builder = await importDefault("../lib/builder.js");
|
|
56
|
-
const b = builder({ env: Env(process.cwd()).all });
|
|
57
|
-
b.dockerRemoteBuildV2(context, options.file);
|
|
58
|
-
});
|
|
71
|
+
},
|
|
72
|
+
});
|
|
59
73
|
|
|
60
|
-
|
|
74
|
+
program.command({
|
|
75
|
+
command: "build [context]",
|
|
76
|
+
desc: "构建",
|
|
77
|
+
builder: (args) => {
|
|
78
|
+
args.option("f", {
|
|
79
|
+
alias: "file",
|
|
80
|
+
describe: "Dockerfile",
|
|
81
|
+
default: "Dockerfile",
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
handler: async ({ context, file }) => {
|
|
85
|
+
const Builder = await importDefault("../lib/builder.js");
|
|
86
|
+
Env.load(process.cwd());
|
|
87
|
+
const b = new Builder({ env: Env.all });
|
|
88
|
+
b.dockerRemoteBuildV2(context, file);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
61
91
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
92
|
+
let devSubCommands = [
|
|
93
|
+
{
|
|
94
|
+
command: "forward [addr]",
|
|
95
|
+
desc: "本地端口转发",
|
|
96
|
+
handler: async ({ addr }) => {
|
|
97
|
+
const { dev } = await importDefault("../cmds/dev.js");
|
|
98
|
+
await dev(addr);
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
command: "shell",
|
|
103
|
+
desc: "远程连接盒子",
|
|
104
|
+
builder: (args) => {
|
|
105
|
+
args.option("b", {
|
|
106
|
+
alias: "build",
|
|
107
|
+
desc: "重新部署应用",
|
|
108
|
+
type: "boolean",
|
|
109
|
+
});
|
|
110
|
+
},
|
|
111
|
+
handler: async (args) => {
|
|
112
|
+
const { devShell } = await importDefault("../cmds/dev.js");
|
|
113
|
+
await devShell(args);
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
program.command({
|
|
118
|
+
command: "dev",
|
|
119
|
+
desc: "dev [forward [addr] | shell]",
|
|
120
|
+
builder: (args) => {
|
|
121
|
+
args.command(devSubCommands);
|
|
122
|
+
},
|
|
123
|
+
});
|
|
69
124
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
.action(async (projectName) => {
|
|
125
|
+
program.command({
|
|
126
|
+
command: "log [project]",
|
|
127
|
+
desc: "查看应用日志",
|
|
128
|
+
builder: (args) => {
|
|
129
|
+
args.option("u", {
|
|
130
|
+
alias: "user",
|
|
131
|
+
describe: "多实例对应的用户",
|
|
132
|
+
demandOption: true,
|
|
133
|
+
type: "string",
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
handler: async (args) => {
|
|
83
137
|
const { monitor } = await importDefault("../cmds/log.js");
|
|
84
|
-
await monitor(
|
|
85
|
-
}
|
|
138
|
+
await monitor(args.project, args);
|
|
139
|
+
},
|
|
140
|
+
});
|
|
86
141
|
|
|
87
|
-
program
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
142
|
+
program.command({
|
|
143
|
+
command: "config [key] [value]",
|
|
144
|
+
desc: "应用配置项",
|
|
145
|
+
builder: (args) => {
|
|
146
|
+
args.implies("key", "value");
|
|
147
|
+
args.option("g", {
|
|
148
|
+
alias: "global",
|
|
149
|
+
describe: "global config",
|
|
150
|
+
type: "boolean",
|
|
151
|
+
default: false,
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
handler: async (args) => {
|
|
94
155
|
const { config } = await importDefault("../cmds/config.js");
|
|
95
|
-
await config([key, value,
|
|
96
|
-
}
|
|
156
|
+
await config([args.key, args.value, args]);
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
boxCommand(program);
|
|
97
161
|
|
|
98
|
-
program.parse(
|
|
162
|
+
program.parse();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
version: "3.9"
|
|
2
2
|
x-lazycat-app:
|
|
3
3
|
id: ${APP_ID}
|
|
4
|
-
title: ${
|
|
5
|
-
version:
|
|
4
|
+
title: ${APP_DESCRIPTION}
|
|
5
|
+
version: ${APP_VERSION}
|
|
6
6
|
description:
|
|
7
7
|
icon: icon.svg
|
|
8
8
|
categories:
|
|
@@ -12,6 +12,4 @@ x-lazycat-app:
|
|
|
12
12
|
- service: ${APP_ID}
|
|
13
13
|
port: ${HTTP_SERVICE_PORT}
|
|
14
14
|
subdomain: ${APP_ID}
|
|
15
|
-
|
|
16
|
-
- lzcapis
|
|
17
|
-
|
|
15
|
+
auth: auto
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
rego
|
|
2
|
-
====
|
|
1
|
+
# rego
|
|
3
2
|
|
|
4
3
|
Rego is an online Go regular expression tester
|
|
5
4
|
|
|
@@ -9,5 +8,5 @@ It's currently deployed on Heroku at [http://regoio.herokuapp.com/](http://regoi
|
|
|
9
8
|
|
|
10
9
|
## TODO
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
- Sharing (permalink)
|
|
12
|
+
- Add developer documentation
|