@lazycatcloud/lzc-cli 1.1.1 → 1.1.2
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 +38 -30
- package/lib/env.js +276 -57
- 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 -11
- package/lib/sdk.js +7 -10
- package/lib/utils.js +149 -53
- 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,44 +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";
|
|
22
|
-
export const GLOBAL_CONFIG_DIR = path.join(os.homedir(), "/.config/lazycat")
|
|
23
|
+
export const GLOBAL_CONFIG_DIR = path.join(os.homedir(), "/.config/lazycat");
|
|
23
24
|
|
|
24
25
|
export const envsubstr = async (templateContents, args) => {
|
|
25
26
|
const parse = await importDefault("envsub/js/envsub-parser.js");
|
|
26
27
|
return parse(templateContents, args);
|
|
27
28
|
};
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
controller.abort();
|
|
34
|
-
}, 5000);
|
|
35
|
-
|
|
29
|
+
/**
|
|
30
|
+
* 为盒子安装SDK应用
|
|
31
|
+
* @param box_url 盒子入口地址
|
|
32
|
+
**/
|
|
33
|
+
async function InstallSDK(box_url) {
|
|
36
34
|
try {
|
|
37
|
-
|
|
35
|
+
let url = `${box_url}/api/app/apply?id=sdk`;
|
|
36
|
+
const resp = await fetch(url, { method: "post" });
|
|
38
37
|
if (resp.status != 200) {
|
|
39
|
-
throw new Error(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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;
|
|
44
122
|
}
|
|
45
|
-
} catch (error) {
|
|
46
|
-
throw error;
|
|
47
|
-
} finally {
|
|
48
|
-
clearTimeout(timeout);
|
|
49
123
|
}
|
|
124
|
+
return false;
|
|
50
125
|
}
|
|
51
126
|
|
|
127
|
+
/**
|
|
128
|
+
* 确保文件夹存在
|
|
129
|
+
* @param filePath {string} 如果为文件路径 确保其文件夹存在; 如果为文件夹, 则确保该文件夹存在
|
|
130
|
+
*
|
|
131
|
+
*/
|
|
52
132
|
function ensureDir(filePath) {
|
|
53
|
-
|
|
133
|
+
let dirPath;
|
|
134
|
+
if (filePath.endsWith("/")) {
|
|
135
|
+
dirPath = filePath;
|
|
136
|
+
} else {
|
|
137
|
+
dirPath = path.dirname(filePath);
|
|
138
|
+
}
|
|
54
139
|
if (!fs.existsSync(dirPath)) {
|
|
55
140
|
fs.mkdirSync(dirPath, { recursive: true });
|
|
56
141
|
}
|
|
@@ -118,7 +203,7 @@ function getMetaInfo(composeFile) {
|
|
|
118
203
|
return doc[META_MARK];
|
|
119
204
|
}
|
|
120
205
|
|
|
121
|
-
async function
|
|
206
|
+
async function createTemplateFile(templateFile, outputFile, env) {
|
|
122
207
|
const template = yaml.load(fs.readFileSync(templateFile, "utf8"));
|
|
123
208
|
// const meta = template[META_MARK];
|
|
124
209
|
// if (
|
|
@@ -135,7 +220,7 @@ async function convertTemplateFile(templateFile, outputFile, env) {
|
|
|
135
220
|
// authcallback: "/lzcapis/oidc-callback",
|
|
136
221
|
// });
|
|
137
222
|
// template["services"]["lazycat-apis-sidecar"] = {
|
|
138
|
-
// image: "registry.
|
|
223
|
+
// image: "registry.lazycat.cloud/lazycat-apis-sidecar",
|
|
139
224
|
// // volumes_from: ["${APP_NAME}:rw"],
|
|
140
225
|
// volumes: ["lzcapis-lzcapp:/lzcapp"],
|
|
141
226
|
// command: [
|
|
@@ -192,7 +277,7 @@ async function copyDotAppDir(from, to, opts = {}) {
|
|
|
192
277
|
}
|
|
193
278
|
ensureDir(outputFile);
|
|
194
279
|
if (needConvert) {
|
|
195
|
-
await
|
|
280
|
+
await createTemplateFile(templateFile, outputFile, env);
|
|
196
281
|
} else {
|
|
197
282
|
fs.copyFileSync(templateFile, outputFile);
|
|
198
283
|
}
|
|
@@ -256,8 +341,8 @@ function archiveFolder(appDir, format = "zip") {
|
|
|
256
341
|
});
|
|
257
342
|
}
|
|
258
343
|
|
|
259
|
-
function contextDirname() {
|
|
260
|
-
return dirname(fileURLToPath(
|
|
344
|
+
function contextDirname(url = import.meta.url) {
|
|
345
|
+
return dirname(fileURLToPath(url));
|
|
261
346
|
}
|
|
262
347
|
|
|
263
348
|
async function importDefault(pkgPath) {
|
|
@@ -266,39 +351,39 @@ async function importDefault(pkgPath) {
|
|
|
266
351
|
}
|
|
267
352
|
|
|
268
353
|
class GitIgnore {
|
|
269
|
-
constructor() {
|
|
270
|
-
this.
|
|
354
|
+
constructor(root) {
|
|
355
|
+
this.root = root;
|
|
356
|
+
this.ignores = [];
|
|
271
357
|
}
|
|
272
358
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
// if not exist .gitignore
|
|
280
|
-
}
|
|
281
|
-
}
|
|
359
|
+
async collect() {
|
|
360
|
+
const files = await glob(["**/.gitignore"], {
|
|
361
|
+
cwd: this.root,
|
|
362
|
+
dot: true,
|
|
363
|
+
deep: 3,
|
|
364
|
+
});
|
|
282
365
|
|
|
283
|
-
|
|
284
|
-
return this.ig.ignores(filepath);
|
|
366
|
+
files.forEach((f) => this._add(f));
|
|
285
367
|
}
|
|
286
368
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
+
}
|
|
294
378
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
379
|
+
contain(filepath) {
|
|
380
|
+
return this.ignores.some(({ ig, dir }) => {
|
|
381
|
+
// 去除不应该计算ignore 的文件
|
|
382
|
+
if (!filepath.startsWith(dir)) {
|
|
383
|
+
return false;
|
|
298
384
|
}
|
|
299
385
|
|
|
300
|
-
|
|
301
|
-
return callback(err, validFiles);
|
|
386
|
+
return ig.ignores(path.relative(dir, filepath));
|
|
302
387
|
});
|
|
303
388
|
}
|
|
304
389
|
}
|
|
@@ -325,6 +410,12 @@ function urlHostname(url) {
|
|
|
325
410
|
return u.hostname;
|
|
326
411
|
}
|
|
327
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
|
+
|
|
328
419
|
export {
|
|
329
420
|
ensureDir,
|
|
330
421
|
copyDotAppDir,
|
|
@@ -333,7 +424,6 @@ export {
|
|
|
333
424
|
findAppRootPath,
|
|
334
425
|
archiveFolder,
|
|
335
426
|
mergeYaml,
|
|
336
|
-
checkURL,
|
|
337
427
|
loadFromYaml,
|
|
338
428
|
dumpToYaml,
|
|
339
429
|
importDefault,
|
|
@@ -347,4 +437,10 @@ export {
|
|
|
347
437
|
GitIgnore,
|
|
348
438
|
isFileExist,
|
|
349
439
|
urlHostname,
|
|
440
|
+
InstallSDK,
|
|
441
|
+
findAppIsInstalled,
|
|
442
|
+
getInstalledApps,
|
|
443
|
+
checkSDKInstallStatus,
|
|
444
|
+
createTemplateFile,
|
|
445
|
+
parse2CorrectName,
|
|
350
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.2",
|
|
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
|