@lazycatcloud/lzc-cli 1.2.27 → 1.2.28

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.
Files changed (37) hide show
  1. package/lib/app/apkshell.js +37 -0
  2. package/lib/app/index.js +74 -74
  3. package/lib/app/lpk_build.js +113 -117
  4. package/lib/app/lpk_create.js +78 -148
  5. package/lib/app/lpk_create_generator.js +101 -74
  6. package/lib/app/lpk_debug_bridge.js +65 -62
  7. package/lib/app/lpk_devshell.js +227 -228
  8. package/lib/app/lpk_devshell_docker.js +28 -28
  9. package/lib/app/lpk_installer.js +59 -49
  10. package/lib/appstore/index.js +29 -29
  11. package/lib/appstore/login.js +64 -64
  12. package/lib/appstore/prePublish.js +68 -68
  13. package/lib/appstore/publish.js +55 -55
  14. package/lib/box/index.js +25 -25
  15. package/lib/env.js +18 -18
  16. package/lib/shellapi.js +55 -58
  17. package/lib/utils.js +217 -164
  18. package/package.json +7 -1
  19. package/scripts/cli.js +56 -56
  20. package/template/_lpk/manifest.yml.in +8 -8
  21. package/template/vue/README.md +29 -0
  22. package/template/vue/index.html +13 -0
  23. package/template/vue/lzc-build.yml +59 -0
  24. package/template/vue/lzc-icon.png +0 -0
  25. package/template/vue/package.json +20 -0
  26. package/template/vue/public/vite.svg +1 -0
  27. package/template/vue/src/App.vue +30 -0
  28. package/template/vue/src/assets/vue.svg +1 -0
  29. package/template/vue/src/components/HelloWorld.vue +41 -0
  30. package/template/vue/src/main.ts +5 -0
  31. package/template/vue/src/style.css +79 -0
  32. package/template/vue/src/vite-env.d.ts +1 -0
  33. package/template/vue/tsconfig.app.json +24 -0
  34. package/template/vue/tsconfig.json +7 -0
  35. package/template/vue/tsconfig.node.json +22 -0
  36. package/template/vue/vite.config.ts +7 -0
  37. package/template/ionic_vue3/package-lock.json +0 -8100
@@ -1,25 +1,27 @@
1
- import logger from "loglevel";
2
- import inquirer from "inquirer";
1
+ import logger from "loglevel"
2
+ import inquirer from "inquirer"
3
3
  import {
4
4
  contextDirname,
5
5
  loadFromYaml,
6
6
  envTemplateFile,
7
7
  ensureDir,
8
+ ensureDirectoryExists,
8
9
  dumpToYaml,
9
10
  isFileExist,
10
- isValidPackageName,
11
- } from "../utils.js";
12
- import path from "node:path";
13
- import { TemplateConfig } from "./lpk_create_generator.js";
14
- import fs from "node:fs";
15
- import yaml from "js-yaml";
16
- let fsPromises = fs.promises;
11
+ isValidAppId
12
+ } from "../utils.js"
13
+ import path from "node:path"
14
+ import { TemplateConfig } from "./lpk_create_generator.js"
15
+ import fs from "node:fs"
16
+ import yaml from "js-yaml"
17
+ import chalk from "chalk"
18
+ let fsPromises = fs.promises
17
19
 
18
20
  export class LpkManifest {
19
21
  constructor(defaultAppID) {
20
- this.pwd = contextDirname(import.meta.url);
21
- this.manifest = {};
22
- this.defaultAppID = defaultAppID;
22
+ this.pwd = contextDirname(import.meta.url)
23
+ this.manifest = {}
24
+ this.defaultAppID = defaultAppID
23
25
  }
24
26
 
25
27
  async init(manifestFilePath, askInfo = false) {
@@ -27,138 +29,74 @@ export class LpkManifest {
27
29
  manifestFilePath = path.join(
28
30
  this.pwd,
29
31
  "../../template/_lpk/manifest.yml.in"
30
- );
32
+ )
31
33
  }
32
34
 
33
35
  if (askInfo) {
34
- let answer = await this.askLpkInfo();
35
- this.manifest = yaml.load(
36
- await envTemplateFile(manifestFilePath, answer)
37
- );
36
+ let answer = await this.askLpkInfo()
37
+ this.manifest = yaml.load(await envTemplateFile(manifestFilePath, answer))
38
38
  } else {
39
- this.manifest = loadFromYaml(manifestFilePath);
39
+ this.manifest = loadFromYaml(manifestFilePath)
40
40
  }
41
41
  }
42
42
 
43
43
  async create(outputDir) {
44
- let outputFilePath = path.join(outputDir, "lzc-manifest.yml");
45
- logger.debug(`创建文件 ${outputFilePath}`);
46
-
47
- ensureDir(outputFilePath);
48
-
49
- return fsPromises
50
- .access(outputFilePath, fs.constants.F_OK | fs.constants.W_OK)
51
- .then(
52
- async () => {
53
- const questions = [
54
- {
55
- name: "override",
56
- type: "input",
57
- default: "n",
58
- message: "lzc-manifest.yml已经存在,是否覆盖(y/n): ",
59
- },
60
- ];
61
- const answers = await inquirer.prompt(questions);
62
- if (answers.override.toLowerCase() === "y") {
63
- return dumpToYaml(this.manifest, outputFilePath);
64
- }
65
- },
66
- () => {
67
- return dumpToYaml(this.manifest, outputFilePath);
68
- }
69
- );
44
+ let outputFilePath = path.join(outputDir, "lzc-manifest.yml")
45
+ logger.debug(`创建文件 ${outputFilePath}`)
46
+ ensureDir(outputFilePath)
47
+ return dumpToYaml(this.manifest, outputFilePath)
70
48
  }
71
49
 
72
50
  async askLpkInfo() {
73
- const noEmpty = (value) => value != "";
74
- const smartAppId = `cloud.lazycat.app.${this.defaultAppID}`;
75
- const getAppName = (answers) => {
76
- const fields = answers["package"].split(".");
77
- return fields[fields.length - 1];
78
- };
79
- return await inquirer.prompt([
51
+ const { appId } = await inquirer.prompt([
80
52
  {
81
53
  type: "input",
82
- name: "package",
83
- message: `请输入应用ID, 如 ${smartAppId}`,
84
- default: smartAppId,
54
+ name: "appId",
55
+ message: `请输入应用ID, 如(${this.defaultAppID})`,
56
+ default: this.defaultAppID,
85
57
  validate: (input) => {
86
- if (isValidPackageName(input)) {
87
- return true;
58
+ if (isValidAppId(input)) {
59
+ return true
88
60
  } else {
89
- return `应用ID错误,请输入正确的格式, ${smartAppId}`;
61
+ // return `请输入 1-63 位的字母、数字或-,且不能以-开头或结尾。`
62
+ return `请输入 1-63 位的字母、数字。`
90
63
  }
91
- },
92
- },
93
- {
94
- type: "input",
95
- name: "version",
96
- message: "请输入应用版本信息",
97
- default: "0.0.1",
98
- validate: noEmpty,
99
- },
100
- {
101
- type: "input",
102
- name: "subdomain",
103
- message: "请输入应用子域名",
104
- default: getAppName,
105
- validate: (input) => {
106
- if (!/^([a-z]|[0-9]|[\-])+$/.test(input)) {
107
- return "应用名称只能包含(减号,小写字母,数字),请重新输入";
108
- }
109
- return true;
110
- },
111
- },
112
- {
113
- type: "input",
114
- name: "name",
115
- message: "请输入应用名称",
116
- default: getAppName,
117
- validate: noEmpty,
118
- },
119
- {
120
- type: "input",
121
- name: "description",
122
- message: "应用简单的描述信息",
123
- },
124
- {
125
- type: "input",
126
- name: "homepage",
127
- message: "应用主页地址",
128
- },
129
- {
130
- type: "input",
131
- name: "author",
132
- message: "应用作者",
133
- },
134
- ]);
64
+ }
65
+ }
66
+ ])
67
+ const answer = {
68
+ name: appId,
69
+ package: `cloud.lazycat.app.${appId}`,
70
+ subdomain: appId
71
+ }
72
+ return answer
135
73
  }
136
74
  }
137
75
 
138
76
  export class TemplateInit {
139
77
  constructor(cwd, name, type) {
140
- this.cwd = cwd;
141
- this.name = name;
142
- this.type = type;
143
- this.lpkManifest = new LpkManifest(name);
78
+ this.cwd = cwd
79
+ this.name = name
80
+ this.type = type
81
+ this.lpkManifest = new LpkManifest(name)
144
82
  }
145
83
 
146
84
  async init() {
147
85
  if (!this.type) {
148
- this.type = await chooseTemplate();
86
+ this.type = await chooseTemplate()
149
87
  }
150
88
 
151
89
  // 优先使用模板项目自定义的模板文件
152
90
  const typeTemplatePath = path.join(
153
91
  contextDirname(import.meta.url),
154
92
  `../../template/_lpk/${this.type}.manifest.yml.in`
155
- );
156
- const templatePath = isFileExist(typeTemplatePath) ? typeTemplatePath : "";
157
- await this.lpkManifest.init(templatePath, true);
93
+ )
94
+ const templatePath = isFileExist(typeTemplatePath) ? typeTemplatePath : ""
95
+ await this.lpkManifest.init(templatePath, true)
158
96
  }
159
97
 
160
98
  async create() {
161
- await this.lpkManifest.create(path.resolve(this.cwd, this.name));
99
+ await this.lpkManifest.create(path.resolve(this.cwd, this.name))
162
100
  }
163
101
  }
164
102
 
@@ -169,10 +107,10 @@ export async function chooseTemplate() {
169
107
  name: "type",
170
108
  message: "选择项目构建模板",
171
109
  type: "list",
172
- choices: ["lite", "vue3", "vue2", "golang", "ionic_vue3"],
173
- },
110
+ choices: ["vue3"]
111
+ }
174
112
  ])
175
- )["type"];
113
+ )["type"]
176
114
  }
177
115
 
178
116
  // 创建一个应用
@@ -181,50 +119,42 @@ export async function chooseTemplate() {
181
119
  // - 调用模板的hook
182
120
  class LpkCreate {
183
121
  constructor(name, cwd = process.cwd()) {
184
- this.name = name;
185
- this.cwd = cwd ?? process.cwd();
122
+ this.name = name
123
+ this.cwd = cwd ?? process.cwd()
124
+ this.appDir = path.resolve(this.cwd, this.name)
186
125
  }
187
126
 
188
127
  async init() {
189
- ensureDir(path.resolve(this.cwd, this.name, "file"));
190
- return this;
128
+ return this
191
129
  }
192
130
 
193
131
  async exec() {
194
- const type = await chooseTemplate();
195
- const template = new TemplateInit(this.cwd, this.name, type);
196
- await template.init();
197
-
198
- console.log(`初始化项目 ${this.name}`);
199
- await TemplateConfig[type].build(path.resolve(this.cwd, this.name));
132
+ const type = await chooseTemplate()
133
+ const template = new TemplateInit(this.cwd, this.name, type)
134
+ await template.init()
135
+
136
+ console.log(chalk.green(`✨ 初始化项目 ${this.name}`))
137
+ const { isExists, renamedFileName } = ensureDirectoryExists(
138
+ this.appDir,
139
+ true
140
+ )
141
+ if (isExists && renamedFileName) {
142
+ console.warn(
143
+ chalk.yellow(
144
+ `! 检测到相同目录,已自动将旧目录重命名为 ${renamedFileName}`
145
+ )
146
+ )
147
+ }
148
+ await TemplateConfig[type].build(path.resolve(this.cwd, this.name))
200
149
 
201
- console.log("初始化懒猫云应用");
202
- await TemplateConfig[type].after(this.name, this.cwd);
150
+ console.log(chalk.green(`✨ 初始化懒猫云应用`))
151
+ await TemplateConfig[type].after(this.name, this.cwd)
203
152
 
204
- await template.create();
153
+ await template.create()
205
154
  }
206
155
  }
207
156
 
208
157
  export default async (name, cwd = process.cwd()) => {
209
- await fsPromises.access(path.resolve(cwd, name)).then(
210
- async () => {
211
- const questions = [
212
- {
213
- name: "override",
214
- type: "input",
215
- default: "n",
216
- message: "项目已存在,是否覆盖(y/n): ",
217
- },
218
- ];
219
- const answers = await inquirer.prompt(questions);
220
- if (answers.override.toLowerCase() === "y") {
221
- const lpk = await new LpkCreate(name, cwd).init();
222
- return await lpk.exec();
223
- }
224
- },
225
- async () => {
226
- const lpk = await new LpkCreate(name, cwd).init();
227
- return await lpk.exec();
228
- }
229
- );
230
- };
158
+ const lpk = await new LpkCreate(name, cwd).init()
159
+ return await lpk.exec()
160
+ }
@@ -1,111 +1,108 @@
1
- import glob from "fast-glob";
2
- import path from "path";
3
- import fs from "fs";
4
- import { isBinaryFileSync } from "isbinaryfile";
5
- import { contextDirname, isFileExist } from "../utils.js";
6
- import chalk from "chalk";
7
- import { spawnSync } from "node:child_process";
8
- import logger from "loglevel";
1
+ import glob from "fast-glob"
2
+ import path from "path"
3
+ import fs from "fs"
4
+ import { isBinaryFileSync } from "isbinaryfile"
5
+ import { contextDirname, isFileExist } from "../utils.js"
6
+ import chalk from "chalk"
7
+ import { spawnSync } from "node:child_process"
8
+ import logger from "loglevel"
9
9
 
10
- const __dirname = contextDirname(import.meta.url);
10
+ const __dirname = contextDirname(import.meta.url)
11
11
 
12
12
  async function loadFiles(dirPath, prefix = "") {
13
- const templateRoot = path.join(__dirname, "../../template/");
14
- const templateDir = path.join(templateRoot, dirPath);
13
+ const templateRoot = path.join(__dirname, "../../template/")
14
+ const templateDir = path.join(templateRoot, dirPath)
15
15
 
16
- const _files = await glob(["**/*"], { cwd: templateDir });
17
- let content;
18
- let files = {};
16
+ const _files = await glob(["**/*"], { cwd: templateDir })
17
+ let content
18
+ let files = {}
19
19
  for (let p of _files) {
20
- const sourcePath = path.join(templateDir, p);
20
+ const sourcePath = path.join(templateDir, p)
21
21
 
22
- const statInfo = fs.statSync(sourcePath);
23
- const mode = statInfo.mode;
22
+ const statInfo = fs.statSync(sourcePath)
23
+ const mode = statInfo.mode
24
24
  if (isBinaryFileSync(sourcePath)) {
25
- content = fs.readFileSync(sourcePath);
25
+ content = fs.readFileSync(sourcePath)
26
26
  } else {
27
- content = fs.readFileSync(sourcePath, "utf8");
27
+ content = fs.readFileSync(sourcePath, "utf8")
28
28
  }
29
29
  // change _ prefix file into dot file
30
30
  if (p.startsWith("_")) {
31
- p = p.replace("_", ".");
31
+ p = p.replace("_", ".")
32
32
  }
33
33
 
34
34
  files[path.join(prefix, p)] = {
35
35
  content,
36
- mode,
37
- };
36
+ mode
37
+ }
38
38
  }
39
- return files;
39
+ return files
40
40
  }
41
41
 
42
42
  function writeFileTree(target, files) {
43
43
  Object.keys(files).forEach((p) => {
44
- const filePath = path.join(target, p);
44
+ const filePath = path.join(target, p)
45
45
  if (!fs.existsSync(path.dirname(filePath))) {
46
- fs.mkdirSync(path.dirname(filePath), { recursive: true });
46
+ fs.mkdirSync(path.dirname(filePath), { recursive: true })
47
47
  }
48
- logger.debug(`创建文件 ${filePath}`);
49
- fs.writeFileSync(filePath, files[p].content, { mode: files[p].mode });
50
- });
48
+ logger.debug(`创建文件 ${filePath}`)
49
+ fs.writeFileSync(filePath, files[p].content, { mode: files[p].mode })
50
+ })
51
51
  }
52
52
 
53
53
  async function generate(type, to, opts = {}) {
54
- const files = await loadFiles(type, opts.prefix);
55
- writeFileTree(to, files);
54
+ const files = await loadFiles(type, opts.prefix)
55
+ writeFileTree(to, files)
56
56
  }
57
57
 
58
58
  function appendREADME(dir) {
59
- const readme = path.resolve(dir, "README.md");
59
+ const readme = path.resolve(dir, "README.md")
60
60
  const readmeTemplate = path.resolve(
61
61
  __dirname,
62
62
  "../../template/_lpk/README.md"
63
- );
63
+ )
64
64
  if (!isFileExist(readme)) {
65
- fs.copyFileSync(readmeTemplate, readme);
65
+ fs.copyFileSync(readmeTemplate, readme)
66
66
  } else {
67
67
  const contentStream = fs.readFileSync(readmeTemplate, {
68
- encoding: "utf-8",
69
- });
70
- fs.writeFileSync(readme, contentStream, { flag: "a" });
68
+ encoding: "utf-8"
69
+ })
70
+ fs.writeFileSync(readme, contentStream, { flag: "a" })
71
71
  }
72
72
  }
73
73
 
74
74
  function vueTemplate(type) {
75
- const v = type == "vue3" ? "vue@3" : "vue@2";
75
+ const v = type == "vue3" ? "vue@3" : "vue@2"
76
76
  return {
77
77
  build: async (to, option) => {
78
- spawnSync("npm", ["init", v, path.basename(to)], { stdio: "inherit" });
78
+ spawnSync("npm", ["init", v, path.basename(to)], { stdio: "inherit" })
79
79
  },
80
80
  after: async function (name, cwd) {
81
81
  spawnSync("npm", ["install"], {
82
82
  cwd: path.resolve(cwd, name),
83
- stdio: "inherit",
84
- });
83
+ stdio: "inherit"
84
+ })
85
85
 
86
86
  const lzcBuildTemplatePath = path.resolve(
87
87
  __dirname,
88
88
  `../../template/_lpk/vue.lzc-build.yml.in`
89
- );
90
- logger.debug("复制", lzcBuildTemplatePath);
91
- fs.copyFileSync(
92
- lzcBuildTemplatePath,
93
- path.resolve(name, "lzc-build.yml")
94
- );
89
+ )
90
+ logger.debug("复制", lzcBuildTemplatePath)
91
+ fs.copyFileSync(lzcBuildTemplatePath, path.resolve(name, "lzc-build.yml"))
95
92
 
96
93
  const iconPngPath = path.resolve(
97
94
  __dirname,
98
95
  "../../template/_lpk/lazycat.png"
99
- );
100
- fs.copyFileSync(iconPngPath, path.resolve(name, "lazycat.png"));
96
+ )
97
+ fs.copyFileSync(iconPngPath, path.resolve(name, "lazycat.png"))
101
98
 
102
99
  // 更改默认的端口
103
- const packageJson = path.resolve(name, "package.json");
104
- const pkgInfo = JSON.parse(fs.readFileSync(packageJson));
105
- pkgInfo["scripts"]["dev"] = `vite --port 3000 --host`;
106
- fs.writeFileSync(packageJson, JSON.stringify(pkgInfo, null, " "));
100
+ const packageJson = path.resolve(name, "package.json")
101
+ const pkgInfo = JSON.parse(fs.readFileSync(packageJson))
102
+ pkgInfo["scripts"]["dev"] = `vite --port 3000 --host`
103
+ fs.writeFileSync(packageJson, JSON.stringify(pkgInfo, null, " "))
107
104
 
108
- appendREADME(path.resolve(cwd, name));
105
+ appendREADME(path.resolve(cwd, name))
109
106
 
110
107
  console.log(
111
108
  chalk.green(
@@ -116,20 +113,50 @@ function vueTemplate(type) {
116
113
  ${chalk.yellow(`lzc-cli app install ${name}.lpk`)}
117
114
  `.trim()
118
115
  )
119
- );
120
- },
121
- };
116
+ )
117
+ }
118
+ }
119
+ }
120
+
121
+ function appCreateSuccessTip(name) {
122
+ console.log(
123
+ chalk.green(
124
+ `
125
+ ✨ 懒猫微服应用已创建成功 !
126
+ ✨ 进行下面步骤后即可进入容器开发
127
+ cd ${name}
128
+ lzc-cli project devshell
129
+ `.trim()
130
+ )
131
+ )
122
132
  }
123
133
 
124
134
  export const TemplateConfig = {
125
- vue3: vueTemplate("vue3"),
135
+ vue3: {
136
+ build: async (to, option) => {
137
+ await generate("vue", to, option)
138
+ },
139
+ after: async function (name) {
140
+ appCreateSuccessTip(name)
141
+ console.log(
142
+ chalk.green(
143
+ `
144
+ ⚙️ 进入应用容器后执行下面命令:
145
+ npm install
146
+ npm run dev
147
+ `.trim()
148
+ )
149
+ )
150
+ }
151
+ },
152
+ // vue3: vueTemplate("vue3"),
126
153
  vue2: vueTemplate("vue2"),
127
154
  lite: {
128
155
  build: async (to, option) => {
129
- await generate("lite", to, option);
156
+ await generate("lite", to, option)
130
157
  },
131
158
  after: async function (name, cwd) {
132
- appendREADME(path.resolve(cwd, name));
159
+ appendREADME(path.resolve(cwd, name))
133
160
 
134
161
  console.log(
135
162
  chalk.green(
@@ -142,21 +169,21 @@ export const TemplateConfig = {
142
169
  ${chalk.yellow(`lzc-cli app install ${name}.lpk`)}
143
170
  `.trim()
144
171
  )
145
- );
146
- },
172
+ )
173
+ }
147
174
  },
148
175
  ionic_vue3: {
149
176
  build: async (to, option) => {
150
- await generate("ionic_vue3", to, option);
177
+ await generate("ionic_vue3", to, option)
151
178
  },
152
179
  after: async function (name, cwd) {
153
- appendREADME(path.resolve(cwd, name));
180
+ appendREADME(path.resolve(cwd, name))
154
181
 
155
- console.log(chalk.green("开始安装依赖"));
182
+ console.log(chalk.green("开始安装依赖"))
156
183
  spawnSync("npm", ["install"], {
157
184
  cwd: path.join(cwd, name),
158
- stdio: "inherit",
159
- });
185
+ stdio: "inherit"
186
+ })
160
187
 
161
188
  console.log(
162
189
  chalk.green(
@@ -174,15 +201,15 @@ export const TemplateConfig = {
174
201
  ${chalk.yellow(`npm run build_ios`)}
175
202
  `.trim()
176
203
  )
177
- );
178
- },
204
+ )
205
+ }
179
206
  },
180
207
  golang: {
181
208
  build: async (to, option) => {
182
- await generate("golang", to, option);
209
+ await generate("golang", to, option)
183
210
  },
184
211
  after: function (name, cwd) {
185
- appendREADME(path.resolve(cwd, name));
212
+ appendREADME(path.resolve(cwd, name))
186
213
 
187
214
  console.log(
188
215
  chalk.green(
@@ -196,7 +223,7 @@ export const TemplateConfig = {
196
223
  ${chalk.yellow(`lzc-cli app install ${name}.lpk`)}
197
224
  `.trim()
198
225
  )
199
- );
200
- },
201
- },
202
- };
226
+ )
227
+ }
228
+ }
229
+ }