create-blocklet 0.2.17 → 0.3.1

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 +195 -106
  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 +7 -7
  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 +7 -6
  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 +8 -6
  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 +3 -3
  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 +3 -3
  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 +3 -3
  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,28 +74,37 @@ const TYPES = [
68
74
  },
69
75
  ],
70
76
  },
71
- ];
72
-
73
- const SERVICES = [
74
77
  {
75
- name: 'auth',
76
- display: 'Auth Service',
78
+ name: 'api',
77
79
  color: yellow,
80
+ frameworks: [
81
+ {
82
+ name: 'express',
83
+ display: 'express',
84
+ color: yellow,
85
+ },
86
+ ],
78
87
  },
79
88
  ];
80
89
 
81
90
  const renameFiles = {
82
91
  _gitignore: '.gitignore',
83
92
  '_eslintrc.js': '.eslintrc.js',
93
+ _eslintignore: '.eslintignore',
84
94
  _npmrc: '.npmrc',
85
95
  };
86
96
 
87
97
  async function init() {
88
- 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;
89
103
 
90
104
  const defaultProjectName = !targetDir ? 'blocklet-project' : targetDir;
91
105
 
92
106
  let result = {};
107
+ const authorInfo = await getUser();
93
108
 
94
109
  try {
95
110
  result = await prompts(
@@ -136,6 +151,7 @@ async function init() {
136
151
  const TYPE_TITLE = {
137
152
  dapp: 'fullstack: webapp with backend code',
138
153
  static: 'webapp: browser only',
154
+ api: 'api: backend only',
139
155
  };
140
156
  return {
141
157
  title: TYPE_TITLE[type.name],
@@ -162,17 +178,16 @@ async function init() {
162
178
  },
163
179
  },
164
180
  {
165
- type: 'multiselect',
166
- name: 'services',
167
- message: 'Choose blocklet services:',
168
- initial: 0,
169
- choices: SERVICES.map((service) => {
170
- const serviceColor = service.color;
171
- return {
172
- title: serviceColor(service.display),
173
- value: service.name,
174
- };
175
- }),
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 || '',
176
191
  },
177
192
  ],
178
193
  {
@@ -182,12 +197,14 @@ async function init() {
182
197
  }
183
198
  );
184
199
  } catch (cancelled) {
185
- console.log(cancelled.message);
200
+ console.error(cancelled.message);
186
201
  return;
187
202
  }
188
203
 
189
204
  // user choice associated with prompts
190
- const { type, framework, overwrite, packageName, services } = result;
205
+ const { type, framework, overwrite, packageName, authorName, authorEmail } = result;
206
+
207
+ const stopSpinner = startSpinner();
191
208
 
192
209
  const root = path.join(cwd, targetDir);
193
210
 
@@ -197,47 +214,13 @@ async function init() {
197
214
  fs.mkdirSync(root);
198
215
  }
199
216
 
200
- await echoBrand();
201
217
  await echoDocument();
202
218
 
203
219
  console.log('Checking blocklet server runtime environment...', '\n');
204
220
 
205
- const isServerInstalled = checkServerInstalled();
206
- const isSatisfiedVersion = checkSatisfiedVersion();
207
- const isServerRunning = checkServerRunning();
208
-
209
- if (!isServerInstalled) {
210
- // 未安装 blocklet server
211
- console.log(red('To run the blocklet, you need a running blocklet server instance on local machine.'), '\n');
212
- console.log(`Checkout ${green('README.md')} for more usage instructions.`);
213
- console.log('Now you should run:', '\n');
214
- console.log(cyan('npm install -g @blocklet/cli'));
215
- console.log(cyan('blocklet server start -a'));
216
- } else if (!isSatisfiedVersion) {
217
- // 已安装 blocklet server,但版本不满足
218
- console.log(red('Your blocklet server version is outdate, please update it to the latest version.'));
219
- console.log('Now you should run:', '\n');
220
- if (isServerRunning) {
221
- // blocklet server 已经启动
222
- const serverPath = getServerDirectory();
223
- console.log(cyan(`cd ${serverPath}`));
224
- console.log(cyan('blocklet server stop'));
225
- console.log(cyan('npm install -g @blocklet/cli'));
226
- console.log(cyan('blocklet server start'));
227
- console.log(cyan(`cd ${cwd}`));
228
- } else {
229
- // blocklet server 未启动
230
- // TODO: 如何获取未启动的 blocklet server 实例目录?
231
- console.log(cyan('npm install -g @blocklet/cli'));
232
- console.log(cyan('blocklet server start -a'));
233
- }
234
- } else if (!isServerRunning) {
235
- // 已经安装 blocklet server,且版本满足,并且 blocklet server 未启动
236
- console.log(red('You need to start your blocklet server before develop this blocklet.'));
237
- console.log('Now you should run:', '\n');
238
- // TODO: 如何获取未启动的 blocklet server 实例目录?
239
- console.log(cyan('blocklet server start -a'));
240
- }
221
+ const isServerInstalled = await checkServerInstalled();
222
+ const isSatisfiedVersion = await checkSatisfiedVersion();
223
+ const isServerRunning = await checkServerRunning();
241
224
 
242
225
  console.log(`\n\nScaffolding project in ${root}...`);
243
226
 
@@ -253,6 +236,14 @@ async function init() {
253
236
  // eslint-disable-next-line no-continue
254
237
  continue;
255
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
+ }
256
247
  const targetPath = renameFiles[file] ? path.join(root, renameFiles[file]) : path.join(root, file);
257
248
  copy(path.join(commonDir, file), targetPath);
258
249
  }
@@ -277,34 +268,23 @@ async function init() {
277
268
  modifyBlockletMd((md) => {
278
269
  return md.replace(/# template-react/g, `# ${name}`);
279
270
  });
280
- modifyEnv((env) => {
281
- if (framework === 'react') {
282
- env.REACT_APP_TITLE = name;
283
- } else {
284
- env.APP_TITLE = name;
285
- }
286
- return env;
287
- });
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
+ }
288
283
 
289
- // patch blocklet services
290
- modifyBlockletYaml((yamlConfig) => {
291
- if (services.includes('auth')) {
292
- yamlConfig.interfaces[0].services = [
293
- {
294
- name: '@abtnode/auth-service',
295
- config: {
296
- blockUnauthenticated: true,
297
- },
298
- },
299
- ];
300
- }
301
- });
302
284
  // patch blocklet author
303
- modifyBlockletYaml((yamlConfig) => {
304
- // eslint-disable-next-line no-shadow
305
- const { name, email } = getAuthor();
306
- if (name) yamlConfig.author.name = name;
307
- if (email) yamlConfig.author.email = email;
285
+ modifyBlockletYaml(async (yamlConfig) => {
286
+ yamlConfig.author.name = authorName;
287
+ yamlConfig.author.email = authorEmail;
308
288
  });
309
289
 
310
290
  // patch did
@@ -320,23 +300,128 @@ async function init() {
320
300
  pkg.scripts.bundle = ejs.render(pkg.scripts.bundle, { did });
321
301
  }
322
302
  });
323
- const pngIcon = toDidIcon(did, undefined, true);
324
- 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);
325
306
  })();
326
307
 
327
- const pkgManager = /yarn/.test(process.env.npm_execpath) ? 'yarn' : 'npm';
328
-
308
+ const related = path.relative(cwd, root);
329
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
+ }
330
380
 
331
- if (root !== cwd) {
332
- console.log(` ${cyan('cd')} ${path.relative(cwd, root)}`);
333
- }
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
+ }
334
412
 
335
- console.log(cyan(` ${pkgManager === 'yarn' ? 'yarn' : 'npm install'}`));
336
- console.log(cyan('blocklet dev'));
337
- 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)}`));
338
416
 
339
- 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
+ }
340
425
 
341
426
  // inside functions
342
427
  function write(file, content) {
@@ -349,7 +434,10 @@ async function init() {
349
434
  }
350
435
  function read(file) {
351
436
  const targetPath = path.join(root, file);
352
- return fs.readFileSync(targetPath, 'utf8');
437
+ if (fs.existsSync(targetPath)) {
438
+ return fs.readFileSync(targetPath, 'utf8');
439
+ }
440
+ return null;
353
441
  }
354
442
 
355
443
  function modifyPackage(modifyFn = () => {}) {
@@ -370,12 +458,13 @@ async function init() {
370
458
  write('blocklet.md', modifyMd);
371
459
  }
372
460
  function modifyEnv(modifyFn = (...args) => ({ ...args })) {
373
- try {
374
- const env = envfile.parse(read('.env'));
461
+ const envContent = read('.env');
462
+ if (envContent) {
463
+ const env = envfile.parse(envContent);
375
464
  modifyFn(env);
376
465
  write('.env', envfile.stringify(env));
377
- } catch {
378
- 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.')}`);
379
468
  }
380
469
  }
381
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 v0.3.0\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
  }