create-blocklet 0.2.18 → 0.3.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.
Files changed (107) hide show
  1. package/common/.github/workflows/main.yml +5 -5
  2. package/common/.husky/pre-commit +4 -0
  3. package/common/_eslintignore +10 -0
  4. package/common/_eslintrc.js +1 -0
  5. package/common/_gitignore +15 -9
  6. package/common/logo.png +0 -0
  7. package/common/public/favicon.ico +0 -0
  8. package/index.js +200 -77
  9. package/lib/arcblock.js +11 -7
  10. package/lib/git.js +25 -0
  11. package/lib/index.js +17 -5
  12. package/lib/npm.js +7 -9
  13. package/lib/server.js +26 -20
  14. package/package.json +18 -16
  15. package/template-api/express/README.md +146 -0
  16. package/{template-dapp/react/server → template-api/express/api}/hooks/pre-start.js +0 -0
  17. package/template-api/express/api/index.js +13 -0
  18. package/{template-dapp/react/server → template-api/express/api}/libs/auth.js +0 -0
  19. package/{template-dapp/react/server → template-api/express/api}/libs/env.js +0 -0
  20. package/{template-dapp/react/server → template-api/express/api}/libs/logger.js +0 -0
  21. package/template-api/express/blocklet.md +3 -0
  22. package/template-api/express/blocklet.yml +57 -0
  23. package/template-api/express/package.json +26 -0
  24. package/template-api/express/screenshots/.gitkeep +0 -0
  25. package/template-dapp/nextjs/.eslintrc.js +4 -0
  26. package/template-dapp/nextjs/README.md +153 -0
  27. package/template-dapp/{vue/server → nextjs/api}/hooks/pre-start.js +0 -0
  28. package/template-dapp/nextjs/api/index.js +24 -0
  29. package/template-dapp/{vue/server → nextjs/api}/libs/auth.js +0 -0
  30. package/template-dapp/{vue/server → nextjs/api}/libs/env.js +0 -0
  31. package/template-dapp/{vue/server → nextjs/api}/libs/logger.js +0 -0
  32. package/template-dapp/{vue2/server → nextjs/api}/routes/index.js +1 -1
  33. package/template-dapp/nextjs/blocklet.md +3 -0
  34. package/template-dapp/nextjs/blocklet.yml +58 -0
  35. package/template-dapp/nextjs/next.config.js +6 -0
  36. package/template-dapp/nextjs/package.json +48 -0
  37. package/template-dapp/nextjs/pages/_app.js +21 -0
  38. package/template-dapp/nextjs/pages/api/hello.js +5 -0
  39. package/template-dapp/nextjs/pages/index.js +69 -0
  40. package/template-dapp/nextjs/styles/Home.module.css +116 -0
  41. package/template-dapp/nextjs/styles/globals.css +16 -0
  42. package/template-dapp/react/README.md +5 -5
  43. package/template-dapp/{vue2/server → react/api}/hooks/pre-start.js +0 -0
  44. package/template-dapp/react/{server → api}/index.js +0 -0
  45. package/template-dapp/{vue2/server → react/api}/libs/auth.js +0 -0
  46. package/template-dapp/{vue2/server → react/api}/libs/env.js +0 -0
  47. package/template-dapp/{vue2/server → react/api}/libs/logger.js +0 -0
  48. package/template-dapp/react/{server → api}/routes/index.js +1 -1
  49. package/template-dapp/react/blocklet.yml +6 -6
  50. package/template-dapp/react/package.json +35 -23
  51. package/template-dapp/react/public/index.html +1 -3
  52. package/template-dapp/react/src/app.js +8 -8
  53. package/template-dapp/vue/.browserslistrc +4 -0
  54. package/template-dapp/vue/.eslintrc.js +25 -0
  55. package/template-dapp/vue/api/hooks/pre-start.js +33 -0
  56. package/template-dapp/vue/{server → api}/index.js +0 -0
  57. package/template-dapp/vue/api/libs/auth.js +22 -0
  58. package/template-dapp/vue/api/libs/env.js +6 -0
  59. package/template-dapp/vue/api/libs/logger.js +3 -0
  60. package/template-dapp/vue/{server → api}/routes/index.js +1 -1
  61. package/template-dapp/vue/blocklet.yml +6 -5
  62. package/template-dapp/vue/index.html +2 -3
  63. package/template-dapp/vue/package.json +39 -21
  64. package/template-dapp/vue/src/App.vue +4 -2
  65. package/template-dapp/vue/vite.config.js +10 -6
  66. package/template-dapp/vue2/.browserslistrc +4 -0
  67. package/template-dapp/vue2/.eslintrc.js +14 -0
  68. package/template-dapp/vue2/api/hooks/pre-start.js +33 -0
  69. package/template-dapp/vue2/{server → api}/index.js +0 -0
  70. package/template-dapp/vue2/api/libs/auth.js +22 -0
  71. package/template-dapp/vue2/api/libs/env.js +6 -0
  72. package/template-dapp/vue2/api/libs/logger.js +3 -0
  73. package/template-dapp/vue2/api/routes/index.js +6 -0
  74. package/template-dapp/vue2/blocklet.yml +7 -5
  75. package/template-dapp/vue2/jsconfig.json +19 -0
  76. package/template-dapp/vue2/package.json +38 -43
  77. package/template-dapp/vue2/public/index.html +2 -9
  78. package/template-dapp/vue2/src/App.vue +17 -1
  79. package/template-dapp/vue2/src/main.js +0 -2
  80. package/template-dapp/vue2/vue.config.js +0 -1
  81. package/template-static/blocklet-page/package.json +5 -5
  82. package/template-static/react/blocklet.yml +2 -2
  83. package/template-static/react/package.json +21 -9
  84. package/template-static/react/public/index.html +1 -3
  85. package/template-static/react/src/app.js +8 -8
  86. package/template-static/vue/.browserslistrc +4 -0
  87. package/template-static/vue/.eslintrc.js +25 -0
  88. package/template-static/vue/blocklet.yml +2 -2
  89. package/template-static/vue/index.html +2 -3
  90. package/template-static/vue/package.json +26 -8
  91. package/template-static/vue/vite.config.js +10 -6
  92. package/template-static/vue2/.browserslistrc +4 -0
  93. package/template-static/vue2/.eslintrc.js +14 -0
  94. package/template-static/vue2/blocklet.yml +2 -2
  95. package/template-static/vue2/jsconfig.json +19 -0
  96. package/template-static/vue2/package.json +25 -30
  97. package/template-static/vue2/public/index.html +2 -9
  98. package/template-static/vue2/src/App.vue +7 -1
  99. package/template-static/vue2/src/main.js +0 -2
  100. package/template-static/vue2/vue.config.js +0 -3
  101. package/common/public/favicon.svg +0 -1
  102. package/template-dapp/vue2/src/pages/About.vue +0 -13
  103. package/template-dapp/vue2/src/pages/Home.vue +0 -27
  104. package/template-dapp/vue2/src/router.js +0 -24
  105. package/template-static/vue2/src/pages/About.vue +0 -13
  106. package/template-static/vue2/src/pages/Home.vue +0 -20
  107. package/template-static/vue2/src/router.js +0 -24
@@ -27,10 +27,10 @@ jobs:
27
27
  skip-upload: false
28
28
  skip-deploy: false
29
29
  bundle-command: yarn bundle
30
- store-endpoint: ${{ secrets.STORE_ENDPOINT_DEV }}
31
- store-access-token: ${{ secrets.STORE_ACCESS_TOKEN_DEV }}
32
- server-endpoint: ${{ secrets.STAGING_NODE_ENDPOINT }}
33
- server-access-key: ${{ secrets.STAGING_NODE_ACCESS_KEY }}
34
- server-access-secret: ${{ secrets.STAGING_NODE_ACCESS_SECRET }}
30
+ store-endpoint: ${{ secrets.STORE_ENDPOINT }}
31
+ store-access-token: ${{ secrets.STORE_ACCESS_TOKEN }}
32
+ server-endpoint: ${{ secrets.SERVER_ENDPOINT }}
33
+ server-access-key: ${{ secrets.SERVER_ACCESS_KEY }}
34
+ server-access-secret: ${{ secrets.SERVER_ACCESS_SECRET }}
35
35
  slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
36
36
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ . "$(dirname "$0")/_/husky.sh"
3
+
4
+ npx lint-staged
@@ -0,0 +1,10 @@
1
+ public
2
+ dist
3
+ build
4
+
5
+ .blocklet
6
+ node_modules
7
+ .github
8
+ .husky
9
+ *.d.ts
10
+ package.json
@@ -1,4 +1,5 @@
1
1
  module.exports = {
2
+ root: true,
2
3
  parser: 'babel-eslint',
3
4
  extends: '@arcblock/eslint-config',
4
5
  env: {
package/common/_gitignore CHANGED
@@ -1,9 +1,10 @@
1
1
  # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
2
 
3
3
  # dependencies
4
- /node_modules
5
4
  /.pnp
6
5
  .pnp.js
6
+ .DS_Store
7
+ node_modules
7
8
 
8
9
  # testing
9
10
  /coverage
@@ -11,19 +12,24 @@
11
12
  # production
12
13
  /build
13
14
  /dist
15
+ .blocklet
14
16
 
15
- # misc
16
- .DS_Store
17
+ # local env files
17
18
  .env.local
18
- .env.development.local
19
- .env.test.local
20
- .env.production.local
19
+ .env.*.local
21
20
 
21
+ # Log files
22
22
  npm-debug.log*
23
23
  yarn-debug.log*
24
24
  yarn-error.log*
25
+ pnpm-debug.log*
25
26
 
26
- .blocklet
27
- blocklet.js
28
- .DS_Store
27
+ # Editor directories and files
28
+ .idea
29
29
  .vscode
30
+ *.suo
31
+ *.ntvs*
32
+ *.njsproj
33
+ *.sln
34
+ *.sw?
35
+
package/common/logo.png CHANGED
Binary file
Binary file
package/index.js CHANGED
@@ -1,21 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from 'fs';
4
3
  import ejs from 'ejs';
5
- import path from 'path';
6
- import YAML from 'yaml';
4
+ import boxen from 'boxen';
7
5
  import { fileURLToPath } from 'url';
8
- import minimist from 'minimist';
6
+ import { execSync } from 'child_process';
7
+ import { cd, argv, fs, YAML, chalk, path } from 'zx';
8
+ import { startSpinner } from 'zx/experimental';
9
9
  import prompts from 'prompts';
10
- import { yellow, red, green, cyan, blue, lightYellow } from 'kolorist';
11
10
  import * as envfile from 'envfile';
12
11
 
13
12
  import { echoBrand, echoDocument } from './lib/arcblock.js';
14
- import { getAuthor } from './lib/npm.js';
13
+ import { getUser } from './lib/index.js';
15
14
  import { checkServerInstalled, checkServerRunning, checkSatisfiedVersion, getServerDirectory } from './lib/server.js';
16
- import { toBlockletDid, toDidIcon } from './lib/did.js';
15
+ import { toBlockletDid } from './lib/did.js';
16
+ import { initGitRepo } from './lib/git.js';
17
+
18
+ const { yellow, red, green, cyan, blue, bold, dim } = chalk;
17
19
 
18
- const argv = minimist(process.argv.slice(2));
19
20
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
20
21
 
21
22
  const cwd = process.cwd();
@@ -40,6 +41,11 @@ const TYPES = [
40
41
  display: 'vue2 + @vue/cli',
41
42
  color: green,
42
43
  },
44
+ {
45
+ name: 'nextjs',
46
+ display: 'next.js',
47
+ color: blue,
48
+ },
43
49
  ],
44
50
  },
45
51
  {
@@ -68,20 +74,37 @@ const TYPES = [
68
74
  },
69
75
  ],
70
76
  },
77
+ {
78
+ name: 'api',
79
+ color: yellow,
80
+ frameworks: [
81
+ {
82
+ name: 'express',
83
+ display: 'express',
84
+ color: yellow,
85
+ },
86
+ ],
87
+ },
71
88
  ];
72
89
 
73
90
  const renameFiles = {
74
91
  _gitignore: '.gitignore',
75
92
  '_eslintrc.js': '.eslintrc.js',
93
+ _eslintignore: '.eslintignore',
76
94
  _npmrc: '.npmrc',
77
95
  };
78
96
 
79
97
  async function init() {
80
- let targetDir = argv._[0];
98
+ const { version } = await fs.readJSONSync(path.resolve(__dirname, 'package.json'));
99
+
100
+ await echoBrand({ version });
101
+
102
+ let targetDir = argv._[0] ? String(argv._[0]) : undefined;
81
103
 
82
104
  const defaultProjectName = !targetDir ? 'blocklet-project' : targetDir;
83
105
 
84
106
  let result = {};
107
+ const authorInfo = await getUser();
85
108
 
86
109
  try {
87
110
  result = await prompts(
@@ -128,6 +151,7 @@ async function init() {
128
151
  const TYPE_TITLE = {
129
152
  dapp: 'fullstack: webapp with backend code',
130
153
  static: 'webapp: browser only',
154
+ api: 'api: backend only',
131
155
  };
132
156
  return {
133
157
  title: TYPE_TITLE[type.name],
@@ -153,6 +177,18 @@ async function init() {
153
177
  });
154
178
  },
155
179
  },
180
+ {
181
+ type: 'text',
182
+ name: 'authorName',
183
+ message: 'Author name:',
184
+ initial: authorInfo?.name || '',
185
+ },
186
+ {
187
+ type: 'text',
188
+ name: 'authorEmail',
189
+ message: 'Author email:',
190
+ initial: authorInfo?.email || '',
191
+ },
156
192
  ],
157
193
  {
158
194
  onCancel: () => {
@@ -161,12 +197,14 @@ async function init() {
161
197
  }
162
198
  );
163
199
  } catch (cancelled) {
164
- console.log(cancelled.message);
200
+ console.error(cancelled.message);
165
201
  return;
166
202
  }
167
203
 
168
204
  // user choice associated with prompts
169
- const { type, framework, overwrite, packageName } = result;
205
+ const { type, framework, overwrite, packageName, authorName, authorEmail } = result;
206
+
207
+ const stopSpinner = startSpinner();
170
208
 
171
209
  const root = path.join(cwd, targetDir);
172
210
 
@@ -176,47 +214,13 @@ async function init() {
176
214
  fs.mkdirSync(root);
177
215
  }
178
216
 
179
- await echoBrand();
180
217
  await echoDocument();
181
218
 
182
219
  console.log('Checking blocklet server runtime environment...', '\n');
183
220
 
184
- const isServerInstalled = checkServerInstalled();
185
- const isSatisfiedVersion = checkSatisfiedVersion();
186
- const isServerRunning = checkServerRunning();
187
-
188
- if (!isServerInstalled) {
189
- // 未安装 blocklet server
190
- console.log(red('To run the blocklet, you need a running blocklet server instance on local machine.'), '\n');
191
- console.log(`Checkout ${green('README.md')} for more usage instructions.`);
192
- console.log('Now you should run:', '\n');
193
- console.log(cyan('npm install -g @blocklet/cli'));
194
- console.log(cyan('blocklet server start -a'));
195
- } else if (!isSatisfiedVersion) {
196
- // 已安装 blocklet server,但版本不满足
197
- console.log(red('Your blocklet server version is outdate, please update it to the latest version.'));
198
- console.log('Now you should run:', '\n');
199
- if (isServerRunning) {
200
- // blocklet server 已经启动
201
- const serverPath = getServerDirectory();
202
- console.log(cyan(`cd ${serverPath}`));
203
- console.log(cyan('blocklet server stop'));
204
- console.log(cyan('npm install -g @blocklet/cli'));
205
- console.log(cyan('blocklet server start'));
206
- console.log(cyan(`cd ${cwd}`));
207
- } else {
208
- // blocklet server 未启动
209
- // TODO: 如何获取未启动的 blocklet server 实例目录?
210
- console.log(cyan('npm install -g @blocklet/cli'));
211
- console.log(cyan('blocklet server start -a'));
212
- }
213
- } else if (!isServerRunning) {
214
- // 已经安装 blocklet server,且版本满足,并且 blocklet server 未启动
215
- console.log(red('You need to start your blocklet server before develop this blocklet.'));
216
- console.log('Now you should run:', '\n');
217
- // TODO: 如何获取未启动的 blocklet server 实例目录?
218
- console.log(cyan('blocklet server start -a'));
219
- }
221
+ const isServerInstalled = await checkServerInstalled();
222
+ const isSatisfiedVersion = await checkSatisfiedVersion();
223
+ const isServerRunning = await checkServerRunning();
220
224
 
221
225
  console.log(`\n\nScaffolding project in ${root}...`);
222
226
 
@@ -232,6 +236,14 @@ async function init() {
232
236
  // eslint-disable-next-line no-continue
233
237
  continue;
234
238
  }
239
+ if (framework === 'blocklet-page' && ['_eslintignore', '.husky'].includes(file)) {
240
+ // eslint-disable-next-line no-continue
241
+ continue;
242
+ }
243
+ if (framework === 'express' && ['_eslintignore', '.husky'].includes(file)) {
244
+ // eslint-disable-next-line no-continue
245
+ continue;
246
+ }
235
247
  const targetPath = renameFiles[file] ? path.join(root, renameFiles[file]) : path.join(root, file);
236
248
  copy(path.join(commonDir, file), targetPath);
237
249
  }
@@ -256,21 +268,23 @@ async function init() {
256
268
  modifyBlockletMd((md) => {
257
269
  return md.replace(/# template-react/g, `# ${name}`);
258
270
  });
259
- modifyEnv((env) => {
260
- if (framework === 'react') {
261
- env.REACT_APP_TITLE = name;
262
- } else {
263
- env.APP_TITLE = name;
264
- }
265
- return env;
266
- });
271
+ if (!['blocklet-page'].includes(framework)) {
272
+ modifyEnv((env) => {
273
+ if (['react'].includes(framework)) {
274
+ env.REACT_APP_TITLE = name;
275
+ } else if (['vue', 'blocklet-page'].includes(framework)) {
276
+ env.VITE_APP_TITLE = name;
277
+ } else {
278
+ env.APP_TITLE = name;
279
+ }
280
+ return env;
281
+ });
282
+ }
267
283
 
268
284
  // patch blocklet author
269
- modifyBlockletYaml((yamlConfig) => {
270
- // eslint-disable-next-line no-shadow
271
- const { name, email } = getAuthor();
272
- if (name) yamlConfig.author.name = name;
273
- if (email) yamlConfig.author.email = email;
285
+ modifyBlockletYaml(async (yamlConfig) => {
286
+ yamlConfig.author.name = authorName;
287
+ yamlConfig.author.email = authorEmail;
274
288
  });
275
289
 
276
290
  // patch did
@@ -286,23 +300,128 @@ async function init() {
286
300
  pkg.scripts.bundle = ejs.render(pkg.scripts.bundle, { did });
287
301
  }
288
302
  });
289
- const pngIcon = toDidIcon(did, undefined, true);
290
- fs.writeFileSync(path.join(root, 'logo.png'), pngIcon);
303
+ // disabled random logo
304
+ // const pngIcon = toDidIcon(did, undefined, true);
305
+ // fs.writeFileSync(path.join(root, 'logo.png'), pngIcon);
291
306
  })();
292
307
 
293
- const pkgManager = /yarn/.test(process.env.npm_execpath) ? 'yarn' : 'npm';
294
-
308
+ const related = path.relative(cwd, root);
295
309
  console.log('\n\n✨ Done. Now run:\n');
310
+ stopSpinner();
311
+
312
+ // const pkgManager =
313
+ // // eslint-disable-next-line no-nested-ternary
314
+ // /pnpm/.test(process.env.npm_execpath) || /pnpm/.test(process.env.npm_config_user_agent)
315
+ // ? 'pnpm'
316
+ // : /yarn/.test(process.env.npm_execpath)
317
+ // ? 'yarn'
318
+ // : 'npm';
319
+ try {
320
+ const { yes } = await prompts(
321
+ {
322
+ type: 'confirm',
323
+ name: 'yes',
324
+ initial: 'Y',
325
+ message: 'Install and start it now?',
326
+ },
327
+ {
328
+ onCancel: () => {
329
+ throw new Error(`${red('✖')} Operation cancelled`);
330
+ },
331
+ }
332
+ );
333
+ let hasStart = false;
334
+
335
+ await initGitRepo(root);
336
+
337
+ let defaultAgent = 'npm';
338
+ let agentList = ['npm', 'yarn', 'pnpm'];
339
+ switch (framework) {
340
+ case 'react':
341
+ case 'blocklet-page':
342
+ agentList = ['npm', 'yarn'];
343
+ break;
344
+ default:
345
+ break;
346
+ }
347
+ if (yes) {
348
+ const { agent } = await prompts({
349
+ name: 'agent',
350
+ type: 'select',
351
+ message: 'Select npm client (package manager)',
352
+ choices: agentList.map((i) => ({ value: i, title: i })),
353
+ });
354
+
355
+ if (!agent) {
356
+ return;
357
+ }
358
+ defaultAgent = agent;
359
+
360
+ await cd(root);
361
+ execSync(`${agent} install`, { stdio: 'inherit' });
362
+ if (isServerInstalled && isServerRunning && isSatisfiedVersion) {
363
+ console.log(
364
+ boxen(bold('blocklet dev'), {
365
+ padding: 1,
366
+ margin: 1,
367
+ float: 'center',
368
+ })
369
+ );
370
+ hasStart = true;
371
+ execSync('blocklet dev', { stdio: 'inherit' });
372
+ } else {
373
+ console.log();
374
+ console.log();
375
+ }
376
+ } else {
377
+ console.log();
378
+ console.log();
379
+ }
296
380
 
297
- if (root !== cwd) {
298
- console.log(` ${cyan('cd')} ${path.relative(cwd, root)}`);
299
- }
381
+ if (!isServerInstalled) {
382
+ // 未安装 blocklet server
383
+ console.log(red('To run the blocklet, you need a running blocklet server instance on local machine.'), '\n');
384
+ console.log(`Checkout ${green('README.md')} for more usage instructions.`);
385
+ console.log('Now you should run:', '\n');
386
+ console.log(cyan(`${defaultAgent} install -g @blocklet/cli`));
387
+ console.log(cyan('blocklet server start -a'));
388
+ } else if (!isSatisfiedVersion) {
389
+ // 已安装 blocklet server,但版本不满足
390
+ console.log(red('Your blocklet server version is outdate, please update it to the latest version.'));
391
+ console.log('Now you should run:', '\n');
392
+ if (isServerRunning) {
393
+ // blocklet server 已经启动
394
+ const serverPath = await getServerDirectory();
395
+ console.log(cyan(`cd ${serverPath}`));
396
+ console.log(cyan('blocklet server stop'));
397
+ console.log(cyan(`${defaultAgent} install -g @blocklet/cli`));
398
+ console.log(cyan('blocklet server start'));
399
+ } else {
400
+ // blocklet server 未启动
401
+ // TODO: 如何获取未启动的 blocklet server 实例目录?
402
+ console.log(cyan(`${defaultAgent} install -g @blocklet/cli`));
403
+ console.log(cyan('blocklet server start -a'));
404
+ }
405
+ } else if (!isServerRunning) {
406
+ // 已经安装 blocklet server,且版本满足,并且 blocklet server 未启动
407
+ console.log(red('You need to start your blocklet server before develop this blocklet.'));
408
+ console.log('Now you should run:', '\n');
409
+ // TODO: 如何获取未启动的 blocklet server 实例目录?
410
+ console.log(cyan('blocklet server start -a'));
411
+ }
300
412
 
301
- console.log(cyan(` ${pkgManager === 'yarn' ? 'yarn' : 'npm install'}`));
302
- console.log(cyan('blocklet dev'));
303
- console.log();
413
+ if (!hasStart) {
414
+ console.log(dim('\n start it later by:\n'));
415
+ if (root !== cwd) console.log(blue(` cd ${bold(related)}`));
304
416
 
305
- console.log(`Find more usage in ${green('README.md')}`, '\n');
417
+ console.log(blue(` ${defaultAgent === 'yarn' ? 'yarn' : `${defaultAgent} install`}`));
418
+ console.log(blue(` ${defaultAgent === 'yarn' ? 'yarn dev' : `${defaultAgent} run dev`}`));
419
+ console.log(cyan('blocklet dev'));
420
+ console.log('\n', `Find more usage in ${green('README.md')}`, '\n');
421
+ }
422
+ } catch (cancelled) {
423
+ console.error(cancelled.message);
424
+ }
306
425
 
307
426
  // inside functions
308
427
  function write(file, content) {
@@ -315,7 +434,10 @@ async function init() {
315
434
  }
316
435
  function read(file) {
317
436
  const targetPath = path.join(root, file);
318
- return fs.readFileSync(targetPath, 'utf8');
437
+ if (fs.existsSync(targetPath)) {
438
+ return fs.readFileSync(targetPath, 'utf8');
439
+ }
440
+ return null;
319
441
  }
320
442
 
321
443
  function modifyPackage(modifyFn = () => {}) {
@@ -336,12 +458,13 @@ async function init() {
336
458
  write('blocklet.md', modifyMd);
337
459
  }
338
460
  function modifyEnv(modifyFn = (...args) => ({ ...args })) {
339
- try {
340
- const env = envfile.parse(read('.env'));
461
+ const envContent = read('.env');
462
+ if (envContent) {
463
+ const env = envfile.parse(envContent);
341
464
  modifyFn(env);
342
465
  write('.env', envfile.stringify(env));
343
- } catch {
344
- console.warn(`\n${lightYellow('No .env file found, please add one.')}`);
466
+ } else {
467
+ console.warn(`\n${yellow('No .env file found, please add one.')}`);
345
468
  }
346
469
  }
347
470
  }
package/lib/arcblock.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import figlet from 'figlet';
2
2
  import terminalLink from 'terminal-link';
3
- import { green } from 'kolorist';
4
3
  import gradient from 'gradient-string';
4
+ import { chalk } from 'zx';
5
5
 
6
- export function echoBrand() {
6
+ const { green } = chalk;
7
+
8
+ export function echoBrand({ version = '' }) {
7
9
  let msg;
8
10
  return new Promise((resolve, reject) => {
9
11
  figlet.text('ArcBlock', { width: 44 }, (err, data) => {
@@ -12,9 +14,11 @@ export function echoBrand() {
12
14
  }
13
15
  const symbolLen = 44;
14
16
  const indent = (symbolLen - 10) / 2;
15
- msg = gradient(['cyan', 'rgb(0, 111, 150)', 'rgb(0, 246,136)']).multiline(
16
- ['', `${' '.repeat(indent)}Powered By`, data].join('\n')
17
- );
17
+ const msgList = [`\n${' '.repeat(indent)}Powered By`, data];
18
+ if (version) {
19
+ msgList.push(`${' '.repeat((symbolLen - 20) / 2)}Create Blocklet v${version}\n`);
20
+ }
21
+ msg = gradient(['cyan', 'rgb(0, 111, 150)', 'rgb(0, 246,136)']).multiline(msgList.join('\n'));
18
22
  console.log(msg);
19
23
  return resolve(msg);
20
24
  });
@@ -26,8 +30,8 @@ export function echoDocument() {
26
30
  if (terminalLink.isSupported) {
27
31
  msg = green(terminalLink(`Documentation: ${url}`, url));
28
32
  } else {
29
- msg = green(`Documentation: ${url}`);
33
+ msg = green(`Check documentation in here: ${url}`);
30
34
  }
31
- console.log(msg, '\n');
35
+ console.log('\n', msg, '\n');
32
36
  return msg;
33
37
  }
package/lib/git.js ADDED
@@ -0,0 +1,25 @@
1
+ import { $, which, cd } from 'zx';
2
+
3
+ $.verbose = false;
4
+
5
+ export async function isGitInstalled() {
6
+ try {
7
+ await which('git');
8
+ return true;
9
+ } catch (e) {
10
+ return false;
11
+ }
12
+ }
13
+
14
+ export async function initGitRepo(root) {
15
+ await cd(root);
16
+ await $`git init`;
17
+ await $`git add .`;
18
+ await $`git commit -m 'init'`;
19
+ }
20
+
21
+ export async function getUserInfo() {
22
+ const { stdout: name } = await $`git config user.name`;
23
+ const { stdout: email } = await $`git config user.email`;
24
+ return { name: name.trim(), email: email.trim() };
25
+ }
package/lib/index.js CHANGED
@@ -1,7 +1,19 @@
1
- /* eslint-disable import/prefer-default-export */
2
- import shell from 'shelljs';
3
- import { stripColors } from 'kolorist';
1
+ import { $ } from 'zx';
2
+ import { getAuthor } from './npm.js';
3
+ import { getUserInfo } from './git.js';
4
4
 
5
- export function getOutput(cmd) {
6
- return stripColors(shell.exec(cmd, { silent: true }).stdout);
5
+ $.verbose = false;
6
+
7
+ export async function getOutput(cmd) {
8
+ const { stdout: output } = await $`${cmd}`;
9
+ return output.trim();
10
+ }
11
+
12
+ export async function getUser() {
13
+ const npmAuthor = await getAuthor();
14
+ const gitUser = await getUserInfo();
15
+ return {
16
+ name: npmAuthor.name || gitUser.name,
17
+ email: npmAuthor.email || gitUser.email,
18
+ };
7
19
  }
package/lib/npm.js CHANGED
@@ -1,13 +1,11 @@
1
- import rc from 'rc';
1
+ /* eslint-disable import/prefer-default-export */
2
+ import { $ } from 'zx';
2
3
 
3
- export function getConfig(key) {
4
- const conf = rc('npm');
5
- return conf?.[key] || '';
6
- }
4
+ $.verbose = false;
7
5
 
8
- export function getAuthor() {
9
- const name = getConfig('init.author.name');
10
- const email = getConfig('init.author.email');
6
+ export async function getAuthor() {
7
+ const { stdout: name } = await $`npm config get init.author.name`;
8
+ const { stdout: email } = await $`npm config get init.author.email`;
11
9
 
12
- return { name, email };
10
+ return { name: name.trim(), email: email.trim() };
13
11
  }
package/lib/server.js CHANGED
@@ -1,38 +1,44 @@
1
+ import { $, which } from 'zx';
1
2
  import semver from 'semver';
2
- import { getOutput } from './index.js';
3
3
 
4
- export function checkServerInstalled() {
5
- const output = getOutput('which blocklet');
6
- return !!output;
4
+ $.verbose = false;
5
+
6
+ export async function checkServerInstalled() {
7
+ try {
8
+ await which('blocklet');
9
+ return true;
10
+ } catch (e) {
11
+ return false;
12
+ }
7
13
  }
8
14
 
9
- export function getServerVersion() {
10
- const output = getOutput('blocklet --version');
15
+ export async function getServerVersion() {
16
+ const { stdout: output } = await $`blocklet --version`;
11
17
  return output.trim();
12
18
  }
13
19
 
14
- export function getServerStatus() {
15
- const output = getOutput('blocklet server status');
16
- const [matchStr] = output.match(/Blocklet Server status:[\s\S]*?\n/g) || [];
17
- if (!matchStr) {
20
+ export async function getServerStatus() {
21
+ try {
22
+ const { stdout: output } = await $`blocklet server status`;
23
+ const [matchStr] = output.match(/Blocklet Server status:[\s\S]*?\n/g) || [];
24
+ const status = matchStr.replace(/Blocklet Server status:\s*(\S+)\s*\S*\n*[\s\S]*/gm, '$1');
25
+ return status.toLowerCase();
26
+ } catch (e) {
18
27
  return 'stop';
19
28
  }
20
- const status = matchStr.replace(/Blocklet Server status:\s*(\S+)\s*\S*\n*[\s\S]*/gm, '$1');
21
- return status.toLowerCase();
22
29
  }
23
- export function checkServerRunning() {
24
- const status = getServerStatus();
30
+ export async function checkServerRunning() {
31
+ const status = await getServerStatus();
25
32
  return status === 'running';
26
33
  }
27
34
 
28
- export function checkSatisfiedVersion() {
29
- const output = getOutput('blocklet --version');
30
- const version = output.trim();
31
- return semver.satisfies(version, '>= 1.6.1');
35
+ export async function checkSatisfiedVersion() {
36
+ const version = await getServerVersion();
37
+ return semver.satisfies(version, '>= 1.7.0');
32
38
  }
33
39
 
34
- export function getServerDirectory() {
35
- const output = getOutput('blocklet server status');
40
+ export async function getServerDirectory() {
41
+ const { stdout: output } = await $`blocklet server status`;
36
42
  const [matchStr] = output.match(/Blocklet Server Data Directory:[\s\S]*?\n/gm) || [];
37
43
  if (!matchStr) return null;
38
44